Execution on Uniswap
Orders that pass the risk engine become swaps on Uniswap v3 through the Universal Router, with tokens pulled by Permit2. The executor is engine/exec-live.mjs. It has no admin function and no way to send ETH or tokens anywhere except through these paths.
The pools
| Stock | Pool | Fee |
|---|---|---|
| NVDA | 0xd4EB21209C4D6093f80B5b84f5C45cc093EA14a3 | 0.05% |
| AAPL | 0xAae0d815EE56e4092a5E5C2911E676Fea50B2d6D | 0.05% |
| MSFT | 0xeb60bCD1D920ad6E102690CCFC6fB488899E1510 | 0.3% |
| TSLA | 0xf4ACdAEEB7022862A763C9B1B885e11191c889E3 | 0.3% |
Each pool trades the stock against USDG (0x5fc5360d0400a0fd4f2af552add042d716f1d168, 6 decimals). In three of the four pools USDG is token0, in TSLA it is token1: the price maths handles both and the tests check both. ETH is priced through the WETH/USDG pool and converted through its 0.05% pool.
One swap
- Approve the token to Permit2 once (maximum), and give the Universal Router a Permit2 allowance (30 days, renewed when it runs low).
- Send
UniversalRouter.executewith the commandV3_SWAP_EXACT_IN: recipient, amount in, minimum amount out, the path (token, fee, token) andpayerIsUser = true. - Measure the result from the wallet balances before and after.
The minimum out is the spot price times the pool fee times (1 - slippagePct). If the pool moved by more than that between the decision and the block, the swap reverts and costs only gas.
SliceOutOfBounds. The engine sends an empty array, which means no extra per-hop check; amountOutMin is the guard.Fills are measured, not assumed
The fill that goes into the ledger is the balance delta: how much USDG left, how much stock arrived. The price in the journal is the real average price of that swap. If a swap fails the cycle logs a RISK line and the ledger is untouched.
Guards in the executor
- A buy larger than the book's cash is refused before any transaction, even if the wallet holds more USDG.
- A sell never asks for more than the wallet holds, and a sale that would leave dust sells the full balance.
- Transactions are sent one at a time, with no provider cache, so two transactions never share a nonce.
ETH to USDG and back
When fees are claimed, the share that goes to the book is wrapped and swapped in one transaction (WRAP_ETH then V3_SWAP_EXACT_IN, paid with the transaction value). For a buyback, USDG is swapped to WETH inside the router and unwrapped to the wallet (UNWRAP_WETH) before the coin is bought on its curve.
How it was tested
tests/fork-live.mjs runs the live executor against a local fork of the chain (real router, real Permit2, real pools, test money) and checks: the buy price against the pool, the balance delta against the reported fill, the inverted TSLA pool, a full sell with no dust, the refusal of an order above the book cash, and both ETH conversions.