Source-Side Atomicity
Source-side atomicity is Sweepster's core defensibility invariant. It states:
The transaction that moves the user's funds must also pay Sweepster — or the entire transaction reverts.
There is no state where Sweepster has advanced gas or value and can be stiffed by a revoked approval, a failing swap, or a worthless token.
Why it matters
Without atomicity, a gasless service is exposed to several failure modes:
- User front-runs the relayer and revokes approval after the relayer pays gas
- Swap output is too low to cover fees
- Token becomes worthless or untradeable between quote and settlement
Sweepster eliminates all of these by making repayment and transfer inseparable at the EVM level.
How it's enforced
The SweepSettlementBase contract executes in a single transaction:
pull tokenIn (EIP-7702 self-pull — the EOA pulls its own tokens)
→ swap to canonical asset
→ compute fees (protocol + builder)
→ skim fees
→ deliver (local or cross-chain)Any failure at any step — including a swap slippage violation — causes the entire transaction to revert. The user's tokens are never moved unless delivery succeeds.
For same-chain delivery, _deliverLocal enforces minAmountOut on the final swap output. For cross-chain delivery, slippage is encoded in the bridge swapCalldata (the witness-bound parameter), and minAmountOut must be 0 in the order itself.
EIP-1153 transient reentrancy guard
The settlement contract uses an EIP-1153 (Cancun) transient storage guard to prevent reentrancy. Unlike a storage-based guard, the transient slot is automatically cleared at the end of the transaction, which is important for the EIP-7702 path: storage set in a constructor is invisible to a 7702-delegated EOA, so transient storage (not constructor-populated mappings) is the correct mechanism.
EIP-7702 settlement path
The product settles exclusively via the SweepDelegate (EIP-7702) path. The user produces two off-chain signatures (no gas):
- An EIP-712 typed-data signature over the
SweepDelegateSweepOrder— verified on-chain asECDSA.recover(toTypedDataHash(domainSeparator(), structHash(order)), sig) == address(this), whereaddress(this)is the user's own EOA. - An EIP-7702 authorization setting their EOA's code to the per-chain
SweepDelegateimplementation for the duration of the transaction.
The relayer broadcasts the type-4 transaction calling the user's address directly. Because address(this) == the user's EOA == order.owner, the delegate pulls its own tokens and executes the swap, fee skim, and delivery atomically in one call frame. The order's deadline bounds the signature; a per-account nonce prevents replay.
The on-chain
SweepRouter/ Permit2 contracts are retained but unused by the product (Permit2 needs an on-chainapprove, which costs gas). They share the sameSweepSettlementBaseatomic logic.
Invariant checklist (for contributors)
Any change to the settlement contracts must preserve:
- [ ] Pull / swap / skim / handoff happen in one reverting transaction
- [ ]
minAmountOutis enforced for same-chain delivery - [ ]
minAmountOut == 0for cross-chain orders (enforced in_validate) - [ ] Fee skim precedes delivery dispatch
- [ ] Reentrancy guard wraps the entire settlement call