Skip to content

Cap WithdrawNativeSol to full balance minus rent - #199

Merged
fedgiac merged 2 commits into
kaze/sc-403-withdraw-sol-from-native-bufferfrom
federico/sc-403-withdraw-sol-from-native-buffer
Oct 12, 2026
Merged

fedgiac merged 2 commits into
kaze/sc-403-withdraw-sol-from-native-bufferfrom
federico/sc-403-withdraw-sol-from-native-buffer

Conversation

@fedgiac

@fedgiac fedgiac commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Implements suggestion from this 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.

@fedgiac
fedgiac requested a review from a team as a code owner October 10, 2026 00:34
@linear-code

linear-code Bot commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

SC-403

@kaze-cow kaze-cow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just wanted to look at the behavior if below minimum rent balance, vyr minor thing. good otherwise.

Comment on lines +52 to +55
.checked_sub(Rent::get()?.try_minimum_balance(native_sol_buffer.data_len())?)
// Basically unreachable: a live buffer is rent-exempt unless the rent
// mechanism itself changed under it.
.ok_or(ProgramError::AccountNotRentExempt)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: since we expect the code to be unreachable anyway, you could say that the only way this could happen is if some protocol upgrade happens in the future. For example, if the cost of rent is raised without requiring older accounts to immediately meet the new rent exempt cap.

in this case, it would be better behavior to simply cap to 0, right? that way the automated script that withdraws funds doesn't suddenly stop working aggressively just because of a protocol upgrade.

In thi particular case it does not seem to be an issue because more funds for rent can simply be deposited into the account, but we should be careful when making assumptions about the rent rules.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I prefer explicit errors, but I agree there are more benefits here to avoid errors in the automated withdraw script.
e096295

// Basically unreachable: a live buffer is rent-exempt unless the rent
// mechanism itself changed under it.
.ok_or(ProgramError::AccountNotRentExempt)?;
let amount = amount.min(withdrawable);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its a little wierd to me that we don't just make amount mutable from the first definition. Guess it basically matters nil, though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general it's good practice to avoid mut so that all mutations of a specific variable are seen explicitly in the code. Not too important here though.

Comment on lines -199 to -216

#[test]
fn process_withdraw_native_sol_rejects_draining_the_buffer() {
assert_rejects(
base_accounts(),
BUFFER_LAMPORTS,
SettlementError::NativeSolBufferEmptied.into(),
);
}

#[test]
fn process_withdraw_native_sol_rejects_more_than_the_balance() {
assert_rejects(
base_accounts(),
BUFFER_LAMPORTS + 1,
ProgramError::ArithmeticOverflow,
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i noticed we removed a few optentially useful tests due to adding the use fo the Rent opcode. I am generally OK with this, and I am not expecting anything I say here to change anything, but I stillu think we should reevaluate our policy on not overriding for purposes of unit testing the sysvars so we can properly unit tests. the benefits are large.

@fedgiac fedgiac Oct 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this isn't nice, but I don't see a clear fix here, it's more of a generic Solana problem with unit testing program code.

@fedgiac
fedgiac requested a review from kaze-cow October 12, 2026 08:31

@kaze-cow kaze-cow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yay

@fedgiac
fedgiac merged commit 250b83a into kaze/sc-403-withdraw-sol-from-native-buffer Oct 12, 2026
18 checks passed
@fedgiac
fedgiac deleted the federico/sc-403-withdraw-sol-from-native-buffer branch October 12, 2026 08:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants