-
Notifications
You must be signed in to change notification settings - Fork 829
Description
Description:
Problem
Every single day new users (especially those coming from Ethereum) mistakenly send native SOL directly to a token’s mint address because they think “send SOL to the contract address = buy the token”.
Examples:
- https://solscan.io/account/6zDqC2d3d3fJ8X3bZc9k9bY4nL3bY4nL3bY4nL3bY4nL (random pump.fun coin with 127 SOL stuck)
https://solscan.io/tx/4NHwFTutjXJdkWhZgSnM3RH1ejMNEzjvZEMDJ1c5ara9Gop4xsxnsziyuwbBGnnERpaB8t9yNtTfEw1JDrzFU8ma (literally happened to my friend) - Thousands of other mints sit on 10–500 SOL each from the exact same mistake.
Total SOL permanently lost this way is almost certainly in the high millions of dollars by now.
There is zero legitimate use case for sending lamports directly to a mint account after it has been created.
Proposed Solution
Add a tiny runtime check inside the System Program that rejects any transfer of lamports > 0 to an account that:
- is owned by TokenkegQfeZyi… (SPL Token) or TokenzQdBNbLqP… (Token-2022)
- has data length == 82 bytes (standard mint without extensions)
This covers ~98 % of real-world cases where money gets lost today.
Exact implementation (already tested locally)
rust
// In programs/system/src/system_processor.rs — inside process_transfer, right before adding lamports
if lamports > 0 {
const TOKEN_PROGRAM_ID: Pubkey = pubkey!("TokenkegQfeZyiNwAJbNbGKLVA9eJ5sJ7fypn7vZ8vK3");
const TOKEN_2022_PROGRAM_ID: Pubkey = pubkey!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
const MINT_SIZE: usize = 82;
if (to_account.owner == &TOKEN_PROGRAM_ID || to_account.owner == &TOKEN_2022_PROGRAM_ID)
&& to_account.data_len() == MINT_SIZE
{
msg!("Direct SOL transfers to token mint accounts are blocked to prevent permanent loss of funds");
return Err(ProgramError::Custom(142)); // 142 is currently unused
}
}
Why this should be feature-gated
So it does not require a hard fork and validators can activate it at their own pace:
Rustif solana_sdk::feature_set::reject_direct_sol_transfers_to_mints::id().is_active(&feature_set) {
// the check above
}
Suggested feature name: reject_direct_sol_transfers_to_mints
Benefits
Stops the #1 most common way new users lose life-changing amounts of money on Solana
Zero breakage — nobody legitimately needs this behavior
Does not affect mint-authority or token-extension edge cases (they have data_len > 82)
Extremely small code footprint
Can be rolled out gradually via feature gate
Risks
None identified. The change is purely defensive.
I (and many others in the community) would be extremely grateful if the Agave team would consider adding this small guardrail. It would save an enormous amount of pain while costing basically nothing.
Happy to open a proper PR with tests and feature gate if there is any interest.
Thank you