GM! Welcome to the Torii Security blog! Here, we delve into Solana security research, conduct thorough security code reviews (audits), and share our thoughts, research, and observations on Solana and beyond.
Today, we’re diving into WSOL, or Wrapped SOL. Wrapped SOL is an SPL token that represents Solana’s native SOL on a 1:1 basis. While native SOL is used to pay transaction fees and rent (storing data in accounts) on the Solana network, WSOL can be used for value transfer operations as it works exactly like any other SPL token.
In this article, I will explain why you might want to avoid using SOL transfers directly in your programs and how WSOL can offer a more versatile alternative. Let’s get started!
Avoid SOL transfers
Here are the main reasons why you should avoid native SOL transfers:
Minimum Lamports Issue: Imagine a protocol that uses native SOL to charge fees. During a swap transaction, the protocol needs to transfer a fee to a designated account. If the fee amount is less than the minimum lamports required for the transaction, the transfer will fail. This can happen if, for example, a user withdraws almost all the lamports from the fee receiver account. When the fee is calculated and it's less than the minimum required lamports, the transaction won't go through, causing a minor denial-of-service (DoS) issue. This happens because Solana requires all accounts to have enough lamports to cover rent. You can check this value using the Rent account function.
More Complicated Code: Protocols often need to support both SPL tokens and native SOL, requiring separate logic for each. This adds complexity to the codebase and can make development and maintenance more cumbersome. Additionally, as your program logic expands, the program size increases, leading to higher SOL costs for deployment.
Indexing Problems: Blockchain explorers struggle with indexing native SOL transfers, making them less transparent for users. In contrast, SPL token transfers are more straightforward to track and display correctly in explorers, providing a clearer view of transactions.
How to use WSOL
Let's take a closer look at how WSOL works in the Solana ecosystem. Essentially, WSOL is a standard SPL token, but it operates in a unique way.
The Logic of WSOL
1. Creating WSOL:
Create Account: First, you need to create a token account for the NATIVE_MINT.
Send Lamports: Then, you should send lamports to the previously created token account.
Sync Native Instruction: Then, you run the sync_native instruction, which:
Retrieves the lamports in the account (leaving some to ensure the account is rent-exempt).
Updates SPL token amount value with lamports allocated to the token account. Notice that the amount value is just synchronized. The lamports are not leaving the account.
2. Converting WSOL Back to SOL:
Simply run the close account instruction, which transfers the lamports back to SOL.
3. Handling Existing WSOL:
If a user already has some WSOL, you can't partially convert WSOL back to SOL; it's all or nothing. However, there is a trick to do it partially:
Create a new token account for the native mint and set the user as the owner.
Transfer the desired amount of WSOL to this new account.
Close the newly created account, which converts the transferred WSOL back to SOL.
User Experience Improvements
As a developer, you can delegate the SOL wrapping and unwrapping process to the user. However, for a better user experience, consider the following scenarios.
Scenario 1: User Doesn't Have Any WSOL
Create an Account for the User:
Create a token account for the user.
Send Lamports:
Transfer lamports to this account.
Run Sync Native Instruction:
Synchronize the native lamports to WSOL.
Perform Desired Instructions:
Carry out the required operations with WSOL.
Close Account (Optional):
To "burn WSOL" and revert to SOL, close the account.
Scenario 2: User Has Some WSOL But Not Enough
Send SOL:
Transfer SOL to the user's WSOL account.
Run Sync Native Instruction:
Synchronize the new lamports to WSOL.
Perform Desired Instructions:
Carry out the required operations with WSOL.
Using Sync Native Instruction
The sync_native instruction is a standard instruction in the token program, so it can be run as a Cross-Program Invocation (CPI) in your Solana program:
/// Given a wrapped / native token account (a token account containing SOL)
/// updates its amount field based on the account's underlying `lamports`.
/// This is useful if a non-wrapped SOL account uses
/// `system_instruction::transfer` to move lamports to a wrapped token
/// account, and needs to have its token `amount` field updated.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` The native token account to sync with its underlying
/// lamports.
SyncNative
However, as you probably already know we are fans of designing programs using the KISS (Keep It Stupid Simple) principle, so it is recommended to abstract WSOL logic away from your program.
Code examples
There are already good code examples on how to wrap and unwrap SOL in the Solana Docs.
Stay in touch
Thank you for reading! To stay updated with our latest insights, research, and security tips, follow us on X and visit our website. If you need help or have any questions, feel free to reach out.
stay safe mantlets, cheers
meltedblocks.