wrapped SOL 与 naive SOL 互相转换

WETH智能合约就比ERC20多了deposit/withdraw进行转换

要获得wSOL需要了解一个指令叫 spl_token::instruction::sync_native

transfer指令(给wSOL的associated_token_addr转SOL) 和 sync_native指令 够了

fn main() {
    // ...
    let token_account = spl_associated_token_account::get_associated_token_address(&payer.pubkey(), &WSOL);
    let latest_block = client.get_latest_blockhash().unwrap();
    get_wsol_balance(&client, &token_account, &payer, latest_block);

    let amount = 1_000_000;
    let instruction = solana_sdk::system_instruction::transfer(&payer.pubkey(), &token_account, amount);
    let transaction = Transaction::new_signed_with_payer(
        &[instruction],
        Some(&payer.pubkey()),
        &[&payer],
        latest_block,
    );
    client.send_and_confirm_transaction(&transaction).unwrap();
    println!("after transfer {amount}");
    get_wsol_balance(&client, &token_account, &payer, latest_block);

    let ix = spl_token::instruction::sync_native(&spl_token::ID, &token_account).unwrap();
    let transaction = Transaction::new_signed_with_payer(
        &[ix],
        Some(&payer.pubkey()),
        &[&payer],
        latest_block,
    );
    client.send_and_confirm_transaction(&transaction).unwrap();
    println!("after sync_native {amount}");
    get_wsol_balance(&client, &token_account, &payer, latest_block);
}
fn get_wsol_balance(client: &RpcClient, token_account: &Pubkey, payer: &Keypair, latest_block: Hash)  {
    let account = match client.get_account(&token_account) {
        Ok(acc) => acc,
        Err(err) => match err.kind {
            solana_client::client_error::ClientErrorKind::RpcError(
                solana_client::rpc_request::RpcError::ForUser(err),
            ) => {
                println!("{}: {err}", line!());
                let create_account_instr = spl_associated_token_account::instruction::create_associated_token_account(
                    &payer.pubkey(),
                    &token_account,
                    &WSOL,
                    &spl_token::ID,
                );
                let mut transaction =
                    Transaction::new_with_payer(&[create_account_instr], Some(&payer.pubkey()));
                transaction.sign(&[&payer], latest_block);
                client.send_and_confirm_transaction(&transaction).unwrap();
                client.get_account(&token_account).unwrap()
            }
            _ => {
                panic!("{err}");
            }
        }  
    };
    let account_state = spl_token::state::Account::unpack(&account.data).unwrap();
    let sol = account_state.amount as f64 / 1e9;
    println!("wsol = {sol}, {} lamports", account_state.amount);
}

代码的输出如下,如果转账给wSOL不进行 sync_native 的话,wSOL 余额是没有更新的

wsol = 0.004, 4000000 lamports
after transfer 1000000
wsol = 0.004, 4000000 lamports
after sync_native 1000000
wsol = 0.005, 5000000 lamports

我们再看看 solana 源码中怎样进行 SOl->wSOL 的

https://github.com/solana-labs/solana-program-library/blob/master/token/cli/src/command.rs#L1886

spl-token cli 源码中,创建spl-token 并没有用 sync_native 原因是先transfer再init账户的话,init的时候相当于执行了类似sync_native的效果了

所以 spl-token wrap 命令在wSOL账户存在的时候转入wSOL会报错Error: Account already exists

只能用transfer+sync_native的方式

solana源码中提到:

Burns tokens by removing them from an account. Burn does not support accounts associated with the native mint, use CloseAccount instead.

不能使用burn去销毁wSOL余额换回原生SOL, 只能用close把wSOL账户全部退回成SOL,不同于WETH合约可以部分提现WETH成ETH

spl-token unwrap实际上调用的是close account

全部评论(0)
推荐文章
Pectra 升级的核心:EIP-7702的原理分析和实操
来 The Web3, 学习史上最全面的区块链教程,挑战高薪
TON钱包签名、私钥导入与发送交易
Rust 实战:构建高效的异步 P2P 网络节点
深入理解solana-keygen
solana账户总结
以太坊POS工作原理详解:Epoch、Slot 与信标区块
以太坊发币 - 超简单发行 ERC-20 代币并上线到 holesky 上
NFT发行 - 超简单发行 NFT 到 holesky 上(包含 ERC165、ERC721Receiver 的含义)
wrapped SOL 与 naive SOL 互相转换
The Web3 社区--区块链运维课程大纲
更安全的签名 - EIP712 结构化签名
带你手搓一个预言机 - 极简版的 ChainLink VRF 随机数生成
The Web3 区块链钱包教程大纲
以太坊代理模式的天花板 - 信标代理
DeFi 项目的基石 - ERC4626 代币金库协议的实现
SOL合约部署调用与销毁
Uniswap价格批量查询与ws订阅行情
智能合约的身份保证 - 数字签名
Solana USDC 转账交易的细节
ERC20授权的更优方案 - ERC20Permit 签名授权
The Web3 社区 Move 共学招募
abigen 工具和 sol! 宏生成智能合约 ABI 数据结构
The Web3 社区第三期区块链技术培训课程火热招生中--四个月高强度挑战,成为区块链技术高手
MPC托管系统工作原理
事件监听 - 合约事件监听的方案汇总
监听合约事件 -- 手把手带你在线、离线部署 The Graph
代币集大成者 - 手搓一个ERC1155合约并上线 holesky
如何成为一名专业的 Web3 产品经理 ——Web3 产品经理课程招募!
Solana ts/rs 代码 nonce-account 签名