Repository navigation
Add WithdrawNativeSol instruction - #198
Merged
Merged
Conversation
Lets the settlement-owned-order authority move lamports out of the native SOL buffer to a recipient of its choosing. The buffer's rent stays put: the runtime rejects leaving it under-funded, and emptying it is rejected with the existing NativeSolBufferEmptied. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
…sol-from-native-buffer
fedgiac
reviewed
Oct 9, 2026
fedgiac
left a comment
Contributor
There was a problem hiding this comment.
Looks good already. A suggestion to make it easier to withdraw.
Comment on lines
+156
to
+162
| /// `WithdrawNativeSol`'s authority account isn't a signer, or doesn't | ||
| /// match the `settlement_owned_order_authority` recorded in the settlement | ||
| /// state PDA. | ||
| UnauthorizedNativeSolWithdrawal = 47, | ||
| /// `WithdrawNativeSol`'s native SOL buffer account isn't the canonical | ||
| /// native SOL buffer PDA. | ||
| NativeSolBufferMismatch = 48, |
Contributor
There was a problem hiding this comment.
Not in this PR, and not before the audit, but we should really clean up all our errors.
This for example should be the same as the settlement-owned order and should have a more generic name. No reason to separate the two. Same for the mismatch, I'm sure there's a generic one.
Implements suggestion from [this comment](#198 (comment)) to silently cap the amount withdrawn in a `WithdrawNativeSol` instruction to the full balance minus the rent. This is done so that a script that automatically withdraws the fees won't occasionally revert if at the same time a settlement is using funds from the native SOL buffer. ### How to test Existing and modified tests.
Contributor
Author
|
I cannot approve my own PR, so I am just going to say: I approve the latest changes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds a
WithdrawNativeSolinstruction (discriminator 12) that moves a givenamountof lamports out of the native SOL buffer to a recipient of the caller's choosing. Only the settlement-owned-order authority can call it.Motivation
Fees paid out in native SOL build up in
NATIVE_SOL_BUFFER_PDA, and right now nothing can get them out. The other buffers are emptied by selling their contents throughCreateSettlementOwnedOrder, but SOL isn't a token, so it can't be the sell side of an order. Because the buffer is owned by the program, we can debit it directly, which makes this a small instruction. See SC-403.Considerations
Which authority
It's gated by
SettlementOwnedOrderAuthority, since that role is already the one trusted with withdrawing fees from the buffers. Adding a new role would have changed the state layout,Initializeargs, the IDL and the CLI just to hold a key that would most likely be the same one anyway. The role's doc comment,DESIGN.mdandSECURITY_DESIGN.mdnow say it can do this too.Protecting the buffer's rent
This uses the same approach as #192: Solana itself rejects a withdrawal that leaves the buffer partly below rent (
InsufficientFundsForRent), so the only case the program has to catch is an empty buffer, which it rejects with the existingNativeSolBufferEmptied. I widened that error's doc to cover both instructions instead of adding a near-duplicate. The only new errors areUnauthorizedNativeSolWithdrawal(46) andNativeSolBufferMismatch(47).Explicit amount vs. sweep
The caller passes an explicit
u64instead of "everything above rent". That way partial withdrawals are possible, and the instruction doesn't have to read theRentsysvar to work out the sweepable amount.Cost
withdraw_native_sol/happy_path_withdraws_to_a_recipient_chosen_by_the_authority: 374 CU. The extra dispatch arm moves 15 other rows by 1–3 CU (all down).Tests
The processor has unit tests for every rejection path and the happy path. Integration tests in
tests/withdraw_native_sol.rscover:How to test
just test. For just this instruction:cargo test --test withdraw_native_sol(afterjust build-program).🤖 Generated with Claude Code