Conversation
Contact and Token addresses now are private structs containing Address. Implemented Deref for them and updated usages.
Contact and Token addresses now are private structs containing Address. Implemented Deref for them and updated usages.
Adds dependency on simulator for solver
These can be added as post-processing step at the callsite. Reverted invalid contracts changes Addressed comments
Co-authored-by: José Duarte <duarte.gmj@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a new debug endpoint, POST /api/v1/debug/simulation, which allows for the simulation of arbitrary orders without requiring them to be stored in the database. The changes include updates to the OpenAPI specification, the addition of a new request handler in the orderbook API, and a corresponding simulation method in the core orderbook logic. Feedback focuses on the SimulationRequest schema, which is currently missing critical fields like validTo, partiallyFillable, and feeAmount that are necessary for realistic simulations. Additionally, the order simulation logic needs to ensure internal consistency by correctly hashing appData and calculating the OrderUid before processing the swap.
ccad001 to
790253a
Compare
a9b4cf4 to
098f938
Compare
098f938 to
031704f
Compare
# Description Based on #4265 Adds a /api/v1/debug/simulation/{uid} endpoint to the orderbook that lets you simulate an order's execution via Tenderly. # Changes - debug_simulation.rs — new API handler that accepts an order UID and returns the Tenderly simulation request + any error - Orderbook::simulate_order() — fetches the order, encodes it as a swap, simulates it, and returns the Tenderly request payload - OrderSimulator struct — wraps SwapSimulator with chain ID context; handles encoding orders into EncodedSwap and running simulations ### Notice **Simulation runs against the current block (not a historical replay at the block the order was filled), and that it uses the original order amounts — so for partially filled orders, the full amount is simulated against the trader's current balance.** ### Follow-up PR - [ ] Add support to simulate on specific block number #4305 - [ ] Add support for partially filled orders. - [ ] Custom order simulation (not an existing one) #4304 Encoding improvements in simulator: - InteractionEncoding trait extracted so both Interaction and InteractionData (from model crate) can be encoded — this allows order pre/post interactions to be encoded directly without manual conversion - WrapperCall struct + encode_wrapper_settlement() function added to handle settlements that go through wrapper contracts - SwapSimulator::fake_swap() extended to support wrapper contracts in the query Supporting changes: - app-data: added wrappers() accessor to expose wrapper calls from app data - configs/orderbook: added config for the new simulator (optional — order_simulation_gas_limit: None keeps existing behavior) - price-estimation: refactored to use the new InteractionEncoding trait - driver/encoding: cleanup — moved some encoding logic to the simulator crate The OpenAPI spec has been updated with: Path `/api/v1/debug/simulation/{uid}` — GET endpoint that takes an order UID and returns 200 (OrderSimulation), 404 (not found), 501 (not enabled), or 500 (internal error). New schemas: - OrderSimulation — top-level response with tenderly_request and optional error - TenderlyRequest — the full Tenderly simulation request structure - SimulationType — enum full | quick | abi: - full (default): Detailed decoded output — call trace, function, inputs/outputs, state diffs, and logs with Solidity types. - quick: Raw, minimal output only. Fastest option; no decoding. - abi: Decoded function inputs/outputs and logs, but no state diffs. Middle ground between quick and full. AccessListItem — address + storage_keys StateObject — balance/code/storage overrides ## How to test Create order in local playground, query for its simulation. Verify on tenderly. Example output: ```json { "tenderly_request": { "network_id": "1", "from": "0xfcc789354262dd9c2f2ff1b0a5f9067b55af1bfa", "to": "0xa513e6e4b8f2a923d98304ec87f64353c4d5c853", "input": "0x13d79a0b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa300000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000009315fc8ffae493123b9b6b1c93d50c9b9eef03440000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000149315fc8ffae493123b9b6b1c93d50c9b9eef03440000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "gas": 16777215, "simulation_type": "full", "save": true, "save_if_fails": true, "state_objects": { "0x68b1d87f95878fe05b998f19b66f4baba5de1aed": { "storage": { "0xd7a1f0b46140686e5b4c405dcbec93c326c8c0e52cb615e05dcf53ad4119c720": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" } }, "0x9315fc8ffae493123b9b6b1c93d50c9b9eef0344": { "code": "0x608060405260043610610037575f3560e01c80631626ba7e1461008d578063542eb77d14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a7366004610b01565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610b9c565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610c00565b610916565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610c3e565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036103e4576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610340573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103649190610c6a565b9050838110156103e2575f6103798286610c81565b90508047106103e0578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156103c8575f5ffd5b505af11580156103da573d5f5f3e3d5ffd5b50505050505b505b505b5f8573ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561042e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104529190610cb9565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9187169063dd62ed3e90604401602060405180830381865afa1580156104c7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104eb9190610c6a565b905084811015610748576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610567575f5ffd5b505af1925050508015610578575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b15801561060b575f5ffd5b505af192505050801561061c575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919088169063dd62ed3e90604401602060405180830381865afa158015610690573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106b49190610c6a565b905085811015610746576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8816906370a0823190602401602060405180830381865afa1580156107b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d69190610c6a565b90508581101561090c5773ffffffffffffffffffffffffffffffffffffffff841663494666b688610807848a610c81565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561086f575f5ffd5b505af1925050508015610880575060015b61090c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b5050505050505050565b61093773ffffffffffffffffffffffffffffffffffffffff8416838361093c565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f906109ce90861683610a46565b90506109d981610a5a565b610a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610a53835f84610a7f565b9392505050565b5f81515f1480610a79575081806020019051810190610a799190610cd4565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610aa89190610c3e565b5f6040518083038185875af1925050503d805f8114610ae2576040519150601f19603f3d011682016040523d82523d5f602084013e610ae7565b606091505b509250905080610af957815160208301fd5b509392505050565b5f5f5f60408486031215610b13575f5ffd5b83359250602084013567ffffffffffffffff811115610b30575f5ffd5b8401601f81018613610b40575f5ffd5b803567ffffffffffffffff811115610b56575f5ffd5b866020828401011115610b67575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b99575f5ffd5b50565b5f5f5f5f5f60a08688031215610bb0575f5ffd5b8535610bbb81610b78565b94506020860135610bcb81610b78565b9350604086013592506060860135610be281610b78565b91506080860135610bf281610b78565b809150509295509295909350565b5f5f5f60608486031215610c12575f5ffd5b8335610c1d81610b78565b92506020840135610c2d81610b78565b929592945050506040919091013590565b5f82515f5b81811015610c5d5760208186018101518583015201610c43565b505f920191825250919050565b5f60208284031215610c7a575f5ffd5b5051919050565b81810381811115610a79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610cc9575f5ffd5b8151610a5381610b78565b5f60208284031215610ce4575f5ffd5b81518015158114610a53575f5ffdfea164736f6c634300081e000a" }, "0xfcc789354262dd9c2f2ff1b0a5f9067b55af1bfa": { "balance": "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" }, "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707": { "code": "0x6080604052348015600e575f5ffd5b50600436106026575f3560e01c806302cc250d14602a575b5f5ffd5b603b6035366004604f565b50600190565b604051901515815260200160405180910390f35b5f60208284031215605e575f5ffd5b813573ffffffffffffffffffffffffffffffffffffffff811681146080575f5ffd5b939250505056fea164736f6c634300081e000a" } } }, "error": null } ``` # Migration Guide: simulation-endpoint branch New field: order-simulation-gas-limit A new optional top-level field has been added to the orderbook TOML configuration. Type: string (decimal integer, interpreted as U256) Default: omitted / disabled ## Enable the order simulation debug endpoint `order-simulation-gas-limit = "16777215"` Effect: When absent (default): the GET `/api/v1/debug/simulation/{uid}` endpoint is disabled. Requests return a 501 Not Implemented response. When present: the endpoint is enabled. The value sets the gas limit used when simulating the order's settlement call via Tenderly (through the price estimation driver's balance-override infrastructure). Recommended value: "16777215" (0xFFFFFF — same as the E2E test default). Adjust downward if you want to cap simulation gas usage. No action required if you do not want to expose the simulation endpoint — omitting the field is the safe default. --------- Co-authored-by: José Duarte <duarte.gmj@gmail.com> Co-authored-by: ilya <ilya@cow.fi>
031704f to
b96c0ea
Compare
fafk
left a comment
There was a problem hiding this comment.
LGTM, but isn't a lot missing? Like simulating different order types, different signatures etc?
|
@fafk I'll add more order details to the request body by re-using OrderCreation struct |
|
Actually, thinking more about it. The signatures etc. are all validated as part of order creation, while it is not strictly necessary to come up with a simulation. I think it does not make much sense for the order simulation endpoint to actually fully validate an order etc, which would limit its ability to experiment with arbitrary orders. The same order that passes simulation (because the interactions, balances, allowances are ok) would be able to fail the validation due to signature checks etc. which I understand is fine. The most important, especially for our partners is to simulate order execution before trying to place it. |
|
As discussed with @fafk, the order simulation request object is going to stay as-is. If it proves not enough for Aave we can always extend it with additional fields per their requirements. |
|
Description
The order simulation endpoint allows one to simulate a specific, existing order. It is useful to be able to simulate any, custom order.
Changes
Implements a POST endpoint
/api/v1/debug/simulationthat allows a request specifying custom order details to be simulated:How to test
E2E test that runs a custom order simulation on a trader with no funds (it reverts), then account is funded and the same request passes.