Repository navigation
feat(buy-sol) PR 2: settle native SOL buys from the state PDA - #4986
Conversation
|
Claude finished @squadgazzz's task in 4m 42s —— View job PR Review: settle native SOL buys from the state PDA
This is clean and well-tested. The I posted one minor inline note about the two different "is native SOL buy" predicates. No blocking issues. One non-blocking heads-up for when BE-331/332 make native buys live: the added |
|
Reminder: Please consider backward compatibility when modifying the API specification.
Caused by: |
Description
Stacked on #4985.
FinalizeSettlepays a native SOL buy from the state PDA's lamports, so the settlement has to put the SOL there first. After #4985 the swap lands as wSOL in the taker's wSOL ATA, so this PR unwraps it and funds the state PDA in the same transaction:The self-transfer moves nothing, it only checks the balance. Without it, a short swap gets topped up from the taker's own SOL and the simulation still passes. Classic SPL Token and p-token both check the balance before they skip the move.
The transfer to the state PDA has to be the exact sum. Until SC-403, lamports leave the state PDA only through pushes, so anything extra gets stuck there. That's also why the ATA closes to the taker and not into the state PDA, and why the solver fee on a native buy stays with the taker. Moving the fee as wSOL into the wSOL buffer would also work. I took the simpler option and I'm open to switching.
The driver creates the wSOL ATA on every settlement that uses it. Settlements aren't serialized yet, so a parallel one can close the ATA after our snapshot. A wSOL sell pays one extra idempotent create for that.
The route also has to leave the wSOL ATA open. Something like Jupiter with
wrapAndUnwrapSol: truewould close it first, and then ourCloseAccountreverts. Our solver has that flag off, so this is about external solvers, and the openapi and solver DTOs spell it out now.Native buys add a few keys and instructions, so a route near the 1,232-byte limit could win at
/solveand fail at/settle./solvenow builds each solution's transaction and drops the ones that don't fit, at onegetMultipleAccountsper solution. This covers all solutions, not only native ones, and a solution it can't build stays in.Nothing reaches this path before BE-331 and BE-332 land. Those drop payouts under 890,880 lamports, since a smaller one into a missing wallet fails the whole settlement, and wallets the System Program doesn't own, which covers the state PDA.
Changes
/solvedrops solutions whose transaction is over the size limitHow to test
New unit and API tests. The workspace has no program harness yet, so barn is the first end to end run. The pre-send simulation stops a broken sequence before it lands.
Related issues
BE-330