Skip to content

Sell Token Account Deallocation on Settlement - #88

Open
kaze-cow wants to merge 10 commits into
mainfrom
kaze/sc-249-aside-what-does-settlement-token-account-deallocation-look
Open

Sell Token Account Deallocation on Settlement#88
kaze-cow wants to merge 10 commits into
mainfrom
kaze/sc-249-aside-what-does-settlement-token-account-deallocation-look

Conversation

@kaze-cow

@kaze-cow kaze-cow commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Description

Closes a sell token account after pulling funds if its empty and the settlement's state account has close_authority

Motivation

There are various places where a feature like this comes in handy:

  • As a piece in a replacement for solflow--since we want to ensure the creation of a WSOL account does not need to be included in the order cost calculations, or remain open after the user's order is processed, we can auto reclaim it for the user once the order is processed.
  • In general if a user is completely cashing out of a token (ex. a throwaway/airdrop), this makes for a really easy way to ensure there is nothing dangling
  • Buffer reclamation--aside from the ReclaimBuffers command which we will already have to close token accounts (reclaim buffer account #60), if we have an instruction that allows for the fee reclaimer to place orders on behalf of the settlement account, the settlement could also close its own buffer account while cashing out all tokens using this method. This should naturally work because the settlement account owns its own buffer accounts!

Moreover, its easy and safe for a user to provide the permission needed to make this happen! SPL tokens provide a separate role explicitly for CloseAuthority, which only allows for the supplied account to close the account once it contains 0 balance. So if the user grants close authority to the settlement program, that can be treated as a certain "opt in". The close authority can be granted as part of the same multicall that places the order.

Considerations

Who receives the rent?

How we determine this can have a signfiicant impact on what flows we support in the above motivations and how many accounts an order uses.

  1. (cheapest) Send funds to buy_token_account. In the case that the buy_token_account is already funded, it would just become surplus rent. In the case that buy_token_account is WETH, we could hypothetically call SyncNative to include the amount in the swap output. This technically keeps funds in the user's control, but locked in the destination account until a future time. This method has the benefit of not consuming an additional token account (since the buy_token_account is duplicated) and you could hypothetically fund the rent for the new token account using the old one (if its NOT token 2022). Ofc this has problems if you are sending to a different receiver, or if you are looking at actually returning funds properly to the user in a way they can actually see in their wallet.
  2. (most natural) Sends funds to the order owner's wallet.
  3. (most flexible) Send tokens to an account specified in the signed OrderIntent. This requires growing the size of the OrderAccount substantially from 201->233 bytes, and the solver would need to specify the target rent recipient as part of the BeginSettle, so this turns out to be substantially more complicated than the other two options above.

After some discussion, we elect to do option 3. This is perhaps the most complicated outcome, but its also the one we are probably going to settle on with this feature.

When to check the sell_account_rent_receiver

This PR has it set up so that the sell_account_rent_receiver account specified by the solver is only checked if the account is to be closed. Otherwise, any account can be specified. Since duplicated accounts do not count towards the maximum transaction accounts limitation in solana, it means that this feature will not negatively impact the maximum orders in a settlement limit unless the sell token account is actually being closed.

Changes were made to add close account handling and grant close account authority through the test cli. This turned out to be a bit more complicated than expected because we need the token account data to determine if the close authority has already been set or not, and I noticed a few minor inconsistencies that I decided to fix while we were here. The PR isn't all that big, but if we want to descope it, we can move the test-cli changes into a separate PR.

Other considerations

Once the sell token account is closed, any Approve that was previously set upon the settlement program will also be cleared. This means, for example, if the user has a partially_fillable = true order and the account runs out of funds before the order is fully complete, the settlement account would close the account, and even if the account is reopened later with new funds, the owner would need to manually re-Approve for the settlement contract to pull the rest of the funds for the order.

Out of Scope

Since the user would be setting their token CloseAuthority to the settlement account, we should also provide an instruction or similar to recover the close authority back to the owner of the token account. This instruction is not included.

Test Plan

  • Confirm suitable test/feature coverage.
  • (optional) try it with the test-cli. Follow the test instructions for making a settlement on Add cow CLI settle command #52 . As long as the conditions are met, without adding any flags, rent will be returned to the payer account for the order.

Example transaction with the close happening:
https://solscan.io/tx/4nBwcUbWqu9xZXBfXYFcaKUteosRCp2BpauTaVamu8qfpZR1cHTvDZ9AqPr3YUynProdTZPmzmFgvbhLVspkZTyd?cluster=devnet

kaze-cow added 4 commits July 30, 2026 16:39
…t-does-settlement-token-account-deallocation-look
this is maybe crossing a threshold of complexity for the begin_settle
function, but it is what it is.
@kaze-cow kaze-cow self-assigned this Aug 4, 2026
@linear-code

linear-code Bot commented Aug 4, 2026

Copy link
Copy Markdown

SC-249

kaze-cow and others added 4 commits August 4, 2026 16:15
…t-does-settlement-token-account-deallocation-look
`create_order` unconditionally granted CloseAuthority to the settlement
state PDA. Default to granting it only when `--sell-account-rent-recipient`
is set, and skip (with a warning) when the sell account already has a
close authority pointing somewhere other than the state PDA.

To make that check possible, `ResolvedToken` now carries the fetched
token account data (`None` when the account is still to be created), and
`instructions::approve` takes the delegate explicitly instead of
re-deriving the state PDA internally.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kaze-cow
kaze-cow marked this pull request as ready for review August 18, 2026 04:27
@kaze-cow
kaze-cow requested a review from a team as a code owner August 18, 2026 04:27
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.

1 participant