IOracle.json.
The observation read has a 200,000 gas limit and runs inside a try block. If that read fails, the program reports observed: false and keeps the successful wrap. Invalid inputs, an unavailable pool or an incorrect wrapped amount revert the whole cook.
Target chains: Base. It names WETH, USDC and UniswapV3.Factory; the pool’s address comes from the factory at run time.
Prerequisites
Install the Sauce CLI to compile and simulate. To send the transaction, configure a wallet with ETH for the program and native coin for gas and the Kitchen fee. KeepIOracle.json in the same directory as the program. See Installation.
Program
pot is the Pot the program runs on, available without declaring it (Names).
low-level-call.sauce.ts
IOracle.json
How it works
evm.call(WETH, wrapAmount, hex`d0e30db0`)is the only way to send value with a call: a bound call never sends any.d0e30db0is the selector ofdeposit(), and the call has no arguments. The program measures the WETH it received rather than reading a return value.observeis not in the registry’sUniswapV3.PoolABI, soimport IOracle from "./IOracle.json"binds it andIOracle.at(pool)calls it at the address the factory returned. Anything bound this way is checked only against the ABI you supply.- The
tryblock holds more than one statement, so it is atomic: if the call, the decode of itsint56[]result or the division fails, the block’s assignments toobservedandmeanTickroll back and the handler runs. Work before the block, the wrap, remains. A.catch()on the call alone would not cover a failure while decoding a successful return. .gas(200000)caps the gas forwarded toobserve, not the transaction’s limit. A read that needs more fails inside thetryand leaves the rest of the cook its gas.int56outputs arrive asInt256, soticks[1] - ticks[0]is a signed difference. Mixed arithmetic needs a conversion, henceInt256(window); signed division truncates toward zero.
Run the example
1
Compile
2
Simulate
--assume-balance ETH:0.01 gives the Pot 0.01 ETH for this simulation only. If your Pot is not deployed yet, the simulation deploys it first.3
Send
--fund ETH:0.01 adds 0.01 ETH to the cook’s value, which lands in the Pot. To sign elsewhere, build the unsigned transactions instead:Simulation result
Simulated on a local fork of Base at block 52965104 with the current contracts. Nothing was signed or sent.window and truncated toward zero.
On the same fork, a window of 4,000,000,000 seconds is older than any observation the pool keeps, so observe reverts inside the try block and the cook still succeeds:
observed and meanTick keep their initial values. On the same fork, with less ETH in the Pot than wrapAmount (--assume-balance ETH:0.005), the guard reverts the cook:
Next steps
- Swap and supply as an actions document: the opposite end, protocol calls written as JSON data.
- Quote two pools, swap on the better one, supply to Aave: the same pools called by name.
- Builtins, Names,
sauce simulate.
