Skip to main content
This program divides a USDC budget among recipients according to their weights. It assigns any rounding remainder to the last recipient so that the payments total exactly the budget. A budget of 0 uses all USDC held by the Pot. Before paying, it checks the recipients and weights. It rejects zero addresses, the Pot itself, duplicate recipients, weights that sum to zero and an unfunded budget. It also verifies the amount each recipient receives. Target chains: Base and Ethereum. The same source compiles for both; the recorded simulations use a Base fork.

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; USDC.balanceOf(pot) reads its USDC balance (Names).
payroll-by-weight.sauce.ts

How it works

  • payees is an array of records, { to: Address; weight: Uint256 }[], passed in --args as a JSON array of objects with the field names as keys.
  • Validation is a separate first loop. The duplicate check compares each payee with every earlier one, so its cost grows with the square of the list length; it runs before the first transfer, so a bad list moves nothing.
  • Math.mulDiv(spend, weight, totalWeight) computes each share as a full-precision product divided by the sum, rounded down. The last payee gets left instead, which absorbs every rounding loss: in the result below, 16,666,667 rather than 16,666,666 base units.
  • main returns Uint256[], one measured amount per payee in input order.

Run the example

1

Compile

Replace base with ethereum. Each compile is 911 bytes, but the bytecode differs, because each carries its chain’s USDC address.
2

Simulate

--assume-balance USDC:150 gives the Pot 150 USDC for this simulation only; the budget is 100 USDC at weights 3:2:1. <payee1>, <payee2> and <payee3> are three different addresses: one address listed twice reverts with “a payee is listed twice”. With 0 as the budget, the program pays out all 150.
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, for 0x7099…79C8, 0x3C44…93BC and 0x90F7…b906. Nothing was signed or sent.
100 USDC at 3:2:1 gives 50 and 33.333333 USDC by rounding down; the last payee received the remaining 16.666667 USDC, so the Pot spent exactly 100 USDC. On the same fork, the guard, with one payee listed twice (0x7099…79C8 in the run):
The check in the first loop reverted the cook before any transfer.

Next steps