Skip to main content
The program sends the Pot’s whole balance of USDC and of WETH, then its whole native balance, to to, and returns the amount that arrived for each. to is its only input. It reverts when to is the zero address or the Pot, or when to ends up with a different amount than the Pot sent. Target chains: Base and Ethereum. The same source compiles for both; the recorded simulations use a Base fork.
The program moves everything the Pot holds of USDC and WETH and all of its native balance. Check to before you send: a wrong address receives all of it.

Prerequisites

Install the Sauce CLI to compile and simulate. To send the transaction, configure a wallet with funds for gas and the Kitchen fee. Provide the required tokens in your Pot once it is deployed, or through --fund; see funding.

Program

pot is the Pot the program runs on, available without declaring it; balanceOf(token, pot) reads its token balance and pot.balance its native coin (Names).
sweep-pot.sauce.ts

How it works

  • The tokens are the registry names [USDC, WETH], and each chain’s compile resolves them to that chain’s addresses, so one file serves Base and Ethereum with no address in it. balanceOf and transfer come from @sauce/token and take the token as their first argument. To sweep other tokens, change the list; sauce globals --chain <chain> --tokens lists the names a chain has.
  • Native value is sent with evm.call(to, value, empty), where empty is an empty hex literal: evm.call is the only way to send value with a call, and empty calldata makes it a plain transfer. A contract at to that refuses native value makes the call fail, which reverts the cook.
  • The return value is one Uint256[] of length tokens.length + 1: USDC, then WETH, then the native amount last. A token the Pot does not hold stays 0 and is not transferred.
  • Each move is measured at to with balanceOf or ctx.balance(to). In the second result below, the native value did not stay in the recipient’s balance, so the guard reverted the cook.

Run the example

1

Compile

Replace base with ethereum. Each compile is 580 bytes, but the bytecode differs, because each carries its chain’s USDC and WETH addresses.
2

Simulate

Each --assume-balance gives the Pot that balance for this simulation only; ETH: sets its native balance.
3

Send

sauce tx prints the unsigned transaction instead, for your own signer:

Simulation result

Simulated on a local fork of Base at block 53159700 with the current contracts, with the command above, sweeping to 0x2154…676d, an address with no code. Nothing was signed or sent.
The Kitchen’s fee was paid from the cook’s value before the program ran, so pot.balance read the 0.002 ETH assumed for the Pot, and all of it arrived at to, as did the 25 USDC and 0.01 WETH. On the same fork, the guard, with 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 as to:
On this fork 0x7099…79C8 has code 0xef0100…, an EIP-7702 delegation, and the 0.002 ETH sent to it did not stay in its balance. The token moves before it were rolled back with the rest of the cook.

Next steps