Skip to content
Merged
Show file tree
Hide file tree
Changes from 101 commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
69ca6c1
Move common eth domain types to separate crate
m-sz Mar 12, 2026
c87657c
tombi format
m-sz Mar 12, 2026
fd4a8d6
Split up acess_list and token_amount
m-sz Mar 12, 2026
d2687f8
fix doc-test
m-sz Mar 12, 2026
b3253a5
Merge branch 'main' into eth-domain-types
m-sz Mar 12, 2026
43510bf
fmt
m-sz Mar 12, 2026
8ba638c
Fully qualify ops
m-sz Mar 13, 2026
6bd3879
Merge branch 'main' into eth-domain-types
m-sz Mar 13, 2026
c89ea6a
Move autopilot specific, non fundamental types back
m-sz Mar 13, 2026
ef5c1af
Remove WethAddress in favour of WrappedNativeToken
m-sz Mar 13, 2026
225f55c
Hide internals of {Contact,Token}Address
m-sz Mar 13, 2026
050a35a
Add Deref to WrappedNativeToken
m-sz Mar 13, 2026
607683e
Migrate driver to eth-domain-types
m-sz Mar 12, 2026
8bb68a1
Hide internals of {Contact,Token}Address
m-sz Mar 13, 2026
59cc93a
Remove driver/src/domain/eth
m-sz Mar 13, 2026
f995199
Add domain/blockchain and flashloan files for driver
m-sz Mar 13, 2026
5e277c5
fmt + doc test fix
m-sz Mar 13, 2026
1d90ff6
Factor out code-fetching to separate crate
m-sz Mar 13, 2026
37bc9f7
Simulator
m-sz Mar 13, 2026
eb1c81f
De-duplicate settlement_encoding
m-sz Mar 17, 2026
9f8994b
Merge branch 'main' into simulator-crate
m-sz Mar 17, 2026
43ea033
Removed debug tracing calls
m-sz Mar 17, 2026
da7aeaf
Small fix
m-sz Mar 17, 2026
612fd75
TOML fmt
m-sz Mar 17, 2026
a922bb7
Remove unused files
m-sz Mar 17, 2026
07da382
Fix copy-and-paste error
m-sz Mar 17, 2026
a050340
Remove interactions from Query
m-sz Mar 18, 2026
d57160e
Merge branch 'main' into simulator-crate
m-sz Mar 18, 2026
3e127b0
Update crates/simulator/src/swap_simulator.rs
m-sz Mar 19, 2026
ec6fc0f
Add docs
m-sz Mar 19, 2026
adb1970
Merge branch 'main' into simulator-crate
m-sz Mar 19, 2026
fd07b5b
Merge branch 'main' into simulator-crate
m-sz Mar 19, 2026
0973507
Add correct solver for trade_verification
m-sz Mar 19, 2026
f61af42
Add debug logs
m-sz Mar 19, 2026
2fa8a08
Simulation endpoint
m-sz Mar 17, 2026
e8bb53e
Clippy + tombi
m-sz Mar 18, 2026
6eefd09
in/out amount logic
m-sz Mar 18, 2026
66b2d03
Fix settlement target for wrapper calls
m-sz Mar 19, 2026
cc93e3c
Error code for when feature is not enabled
m-sz Mar 19, 2026
c0759c2
Revert "Add debug logs"
m-sz Mar 19, 2026
5510e0a
Revert contracts changes
m-sz Mar 19, 2026
15675ae
Merge branch 'simulator-crate' into simulation-endpoint
m-sz Mar 19, 2026
eb4d0a6
Revert contracts changes
m-sz Mar 19, 2026
532ef29
Revert contracts changes 2
m-sz Mar 19, 2026
37f3650
Merge branch 'simulator-crate' into simulation-endpoint
m-sz Mar 19, 2026
03c6ecb
Merge branch 'main' into simulation-endpoint
m-sz Mar 20, 2026
0c604e5
Add state overrides to order simulation
m-sz Mar 20, 2026
a746694
Add order simulation files which I forgot to add before
m-sz Mar 20, 2026
c49cac7
ditto
m-sz Mar 20, 2026
3c034ec
Merge branch 'main' into simulation-endpoint
m-sz Mar 20, 2026
8c5d109
Remove e2e test module
m-sz Mar 20, 2026
cfb72f0
clippy
m-sz Mar 20, 2026
3a65bae
fmt
m-sz Mar 20, 2026
c458cbf
Order simulation E2E test
m-sz Mar 20, 2026
b1f0ab5
Fix e2e test balance overrides config
m-sz Mar 20, 2026
5dde228
lint + add missing file
m-sz Mar 20, 2026
7ae0fe6
Remove e2e test debug logs
m-sz Mar 20, 2026
1d68536
Remove leftover comment
m-sz Mar 20, 2026
b652c16
Addressed comments
m-sz Mar 20, 2026
fb18d06
Make simulation gas limit config option a U256
m-sz Mar 20, 2026
e93ddca
Merge branch 'main' into simulation-endpoint
m-sz Mar 20, 2026
3948d51
Add order simulation TestDefault config
m-sz Mar 20, 2026
7760789
OpenAPI spec
m-sz Mar 20, 2026
9278131
Merge branch 'main' into simulation-endpoint
m-sz Mar 20, 2026
ec7cd91
Fix OpenAPI spec
m-sz Mar 20, 2026
9ce5309
Merge branch 'main' into simulation-endpoint
m-sz Mar 30, 2026
2a66f8d
Merge branch 'main' into simulation-endpoint
m-sz Mar 31, 2026
d6ebe8f
Update crates/orderbook/src/order_simulator.rs
m-sz Mar 31, 2026
f12c0b5
Merge branch 'main' into simulation-endpoint
m-sz Mar 31, 2026
61eb2ca
Doc fix
m-sz Mar 31, 2026
37adc8d
Pass through EncodedSwap in the post processing methods
m-sz Mar 31, 2026
ff1a373
Fix HTTP error codes and update OpenApi spec
m-sz Mar 31, 2026
057a7ed
Change private to public link related to wrapper doc
m-sz Mar 31, 2026
28943f7
Rename in/out amount/token of Query to sell and buy
m-sz Mar 31, 2026
88972d4
Add missing docs, introduce control over how trade is encoded
m-sz Mar 31, 2026
1551f37
Add doc for the simulate_order method
m-sz Mar 31, 2026
c6193d6
Clippy
m-sz Mar 31, 2026
401d44d
Merge branch 'main' into simulation-endpoint
m-sz Mar 31, 2026
0068069
unwrap() -> expect() on wrapper encoding
m-sz Mar 31, 2026
2928583
Update crates/configs/src/orderbook/mod.rs
m-sz Mar 31, 2026
6e94b45
Remove the tenderly request from model crate.
m-sz Mar 31, 2026
dc8c92d
Add warning log when balance overrides can't be set
m-sz Mar 31, 2026
fa43882
Make the simulations full by default
m-sz Mar 31, 2026
d62a7e5
Add TODO comment
m-sz Mar 31, 2026
ccd1924
Orderbook simulator config struct
m-sz Apr 1, 2026
79ef685
unit test fix
m-sz Apr 1, 2026
d1844c8
Update crates/configs/src/orderbook/mod.rs
m-sz Apr 1, 2026
de57faf
Update crates/orderbook/src/order_simulator.rs
m-sz Apr 1, 2026
650a162
Update crates/simulator/src/swap_simulator.rs
m-sz Apr 1, 2026
650b538
Update crates/orderbook/src/dto/mod.rs
m-sz Apr 1, 2026
9f1c702
Update crates/orderbook/src/orderbook.rs
m-sz Apr 1, 2026
2f1a079
Update crates/orderbook/src/order_simulator.rs
m-sz Apr 1, 2026
261eaf0
Fixup docs, use replace + extend for pre interactions
m-sz Apr 1, 2026
3392b1a
Check tenderly request object parameters in e2e test
m-sz Apr 1, 2026
e6aeb2f
Add block number to order simulation
m-sz Apr 1, 2026
790253a
Clippy
m-sz Apr 1, 2026
e2128cf
Add block_number parameter to the OpenAPI spec
m-sz Apr 1, 2026
342b851
Merge branch 'main' into block-number-order-simulation
m-sz Apr 1, 2026
78eaf00
Add block number to order simulation
m-sz Apr 1, 2026
b96c0ea
Custom order simulation
m-sz Apr 1, 2026
ffffdaf
Rework interactions extraction from app data
m-sz Apr 3, 2026
582aad5
Revisit error handling, reduce error logs to warn
m-sz Apr 3, 2026
cb5856a
Handle simulation malformed input errors
m-sz Apr 3, 2026
d45389e
clippy + openapi
m-sz Apr 3, 2026
d213690
Merge simulation e2e tests where applicable
m-sz Apr 3, 2026
c416121
clippy + openapi
m-sz Apr 3, 2026
87175a5
Fix docs, change E2E test request type to the dto
m-sz Apr 7, 2026
e8f9e1e
Fix OpenAPI spec, add error message coverage in e2e tests
m-sz Apr 7, 2026
c2f1c38
Merge branch 'main' into custom-order-simulation
m-sz Apr 7, 2026
96fe72b
Clippy
m-sz Apr 7, 2026
91a54fe
Merge branch 'main' into custom-order-simulation
m-sz Apr 7, 2026
5577531
Fix native price estimation config in E2E test
m-sz Apr 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

194 changes: 194 additions & 0 deletions crates/e2e/tests/e2e/order_simulation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use {
alloy::{primitives::Address, providers::Provider},
configs::test_util::TestDefault,
e2e::setup::{API_HOST, OnchainComponents, Services, run_test},
ethrpc::{Web3, alloy::CallBuilderExt},
Expand All @@ -9,6 +10,7 @@ use {
number::units::EthUnit,
orderbook::dto::OrderSimulationResult,
reqwest::StatusCode,
serde_json::json,
simulator::tenderly::dto::SimulationType,
};

Expand All @@ -18,6 +20,86 @@ async fn local_node_order_simulation() {
run_test(order_simulation).await;
}

#[tokio::test]
#[ignore]
async fn local_node_order_simulation_block_number() {
run_test(order_simulation_block_number).await;
}

#[tokio::test]
#[ignore]
async fn local_node_custom_order_simulation() {
run_test(custom_order_simulation).await;
}

async fn custom_order_simulation(web3: Web3) {
let mut onchain = OnchainComponents::deploy(web3.clone()).await;

let [solver] = onchain.make_solvers(10u64.eth()).await;
let [trader] = onchain.make_accounts(1u64.eth()).await;
let [token] = onchain
.deploy_tokens_with_weth_uni_v2_pools(1_000u64.eth(), 1_000u64.eth())
.await;

let services = Services::new(&onchain).await;
services
.start_protocol_with_args(
configs::autopilot::Configuration::test("test_solver", solver.address()),
configs::orderbook::Configuration::test_default(),
solver,
)
.await;

let client = services.client();
let sell_amount = 1u64.eth();

let body = json!({
"sellToken": token.address(),
"buyToken": onchain.contracts().weth.address(),
"sellAmount": sell_amount.to_string(),
"buyAmount": "1",
"kind": "sell",
"owner": trader.address(),
});
Comment thread
m-sz marked this conversation as resolved.
Outdated

// Trader has no sell tokens — simulation should revert.
let response = client
.post(format!("{API_HOST}/api/v1/debug/simulation"))
.json(&body)
.send()
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let result = response.json::<OrderSimulationResult>().await.unwrap();
assert!(
result.error.is_some(),
Comment thread
m-sz marked this conversation as resolved.
"expected simulation error when trader has no funds"
);

// Fund the trader and approve the vault relayer.
token.mint(trader.address(), sell_amount).await;
token
.approve(onchain.contracts().allowance, sell_amount)
.from(trader.address())
.send_and_watch()
.await
.unwrap();

// Simulation should now succeed.
let response = client
.post(format!("{API_HOST}/api/v1/debug/simulation"))
.json(&body)
.send()
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let result = response.json::<OrderSimulationResult>().await.unwrap();
assert!(
result.error.is_none(),
"expected simulation to pass after funding the trader"
);
}

async fn order_simulation(web3: Web3) {
let mut onchain = OnchainComponents::deploy(web3.clone()).await;

Expand Down Expand Up @@ -87,3 +169,115 @@ async fn order_simulation(web3: Web3) {
assert_eq!(tenderly.simulation_type, Some(SimulationType::Full));
assert_eq!(tenderly.value, None);
}

async fn order_simulation_block_number(web3: Web3) {
let mut onchain = OnchainComponents::deploy(web3.clone()).await;

let [solver] = onchain.make_solvers(10u64.eth()).await;
let [trader] = onchain.make_accounts(10u64.eth()).await;
let [token] = onchain
.deploy_tokens_with_weth_uni_v2_pools(1_000u64.eth(), 1_000u64.eth())
.await;

// Fund trader so the order passes balance validation at submission time.
onchain
.contracts()
.weth
.deposit()
.from(trader.address())
.value(3u64.eth())
.send_and_watch()
.await
.unwrap();
onchain
.contracts()
.weth
.approve(onchain.contracts().allowance, 3u64.eth())
.from(trader.address())
.send_and_watch()
.await
.unwrap();

let services = Services::new(&onchain).await;
services
.start_protocol_with_args(
configs::autopilot::Configuration::test("test_solver", solver.address()),
configs::orderbook::Configuration::test_default(),
solver,
)
.await;

let order = OrderCreation {
sell_token: *onchain.contracts().weth.address(),
sell_amount: 2u64.eth(),
buy_token: *token.address(),
buy_amount: 1u64.eth(),
valid_to: model::time::now_in_epoch_seconds() + 300,
kind: OrderKind::Buy,
..Default::default()
}
.sign(
EcdsaSigningScheme::Eip712,
&onchain.contracts().domain_separator,
&trader.signer,
);
let uid = services.create_order(&order).await.unwrap();

// Transfer all WETH away from the trader — now they have no sell-token
// balance. The current block becomes the "no funds" snapshot.
let burn = Address::from([0x42u8; 20]);
Comment thread
m-sz marked this conversation as resolved.
onchain
.contracts()
.weth
.transfer(burn, 3u64.eth())
.from(trader.address())
.send_and_watch()
.await
.unwrap();
let block_no_funds = web3.provider.get_block_number().await.unwrap();

// Re-deposit WETH. The current block now has the trader fully funded again.
onchain
.contracts()
.weth
.deposit()
.from(trader.address())
.value(3u64.eth())
.send_and_watch()
.await
.unwrap();
let block_with_funds = web3.provider.get_block_number().await.unwrap();

let client = services.client();

// Simulation at the block where the trader had no WETH must fail.
let response = client
.get(format!(
"{API_HOST}/api/v1/debug/simulation/{uid}?block_number={block_no_funds}"
))
.send()
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let result = response.json::<OrderSimulationResult>().await.unwrap();
assert!(
result.error.is_some(),
Comment thread
m-sz marked this conversation as resolved.
"expected simulation failure at block {block_no_funds} (no funds), got success"
);

// Simulation at the block where the trader has WETH must succeed.
let response = client
.get(format!(
"{API_HOST}/api/v1/debug/simulation/{uid}?block_number={block_with_funds}"
))
.send()
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let result = response.json::<OrderSimulationResult>().await.unwrap();
assert_eq!(
result.error, None,
"expected simulation success at block {block_with_funds} (funded), got error: {:?}",
result.error
);
}
1 change: 1 addition & 0 deletions crates/orderbook/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ configs = { workspace = true }
const-hex = { workspace = true }
contracts = { workspace = true }
database = { workspace = true }
eth-domain-types = { workspace = true }
ethrpc = { workspace = true }
futures = { workspace = true }
gas-price-estimation = { workspace = true }
Expand Down
107 changes: 107 additions & 0 deletions crates/orderbook/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,31 @@ paths:
$ref: "#/components/schemas/TotalSurplus"
"400":
description: Invalid address.
"/api/v1/debug/simulation":
post:
operationId: debugSimulationPost
summary: Simulate an arbitrary order.
description: >
Simulates an arbitrary order specified in the request body and returns
the Tenderly simulation request, along with any simulation error if
applicable.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/SimulationRequest"
responses:
"200":
description: Simulation request returned.
content:
application/json:
schema:
$ref: "#/components/schemas/OrderSimulation"
Comment thread
m-sz marked this conversation as resolved.
"405":
description: Order simulation endpoint is not enabled.
"500":
description: Internal error.
"/api/v1/debug/simulation/{uid}":
get:
operationId: debugSimulation
Expand All @@ -778,6 +803,15 @@ paths:
schema:
$ref: "#/components/schemas/UID"
required: true
- in: query
name: block_number
schema:
type: integer
format: int64
required: false
description: >
Block number to simulate the order at. If not specified, the
simulation uses the latest block.
responses:
"200":
description: Simulation request returned.
Expand Down Expand Up @@ -2650,6 +2684,79 @@ components:
- from
- to
- input
SimulationRequest:
description: >
Request body for simulating an arbitrary order without it being stored
in the orderbook.
type: object
properties:
Comment thread
m-sz marked this conversation as resolved.
sellToken:
description: The token being sold.
allOf:
- $ref: "#/components/schemas/Address"
buyToken:
description: The token being bought.
allOf:
- $ref: "#/components/schemas/Address"
sellAmount:
description: Amount of sell token (hex- or decimal-encoded uint256).
allOf:
- $ref: "#/components/schemas/TokenAmount"
buyAmount:
description: Amount of buy token (hex- or decimal-encoded uint256).
allOf:
- $ref: "#/components/schemas/TokenAmount"
kind:
description: Whether this is a sell or buy order.
allOf:
- $ref: "#/components/schemas/OrderKind"
owner:
description: The address of the order owner.
allOf:
- $ref: "#/components/schemas/Address"
receiver:
description: >
The address that will receive the buy tokens. Defaults to the owner
if omitted.
allOf:
- $ref: "#/components/schemas/Address"
nullable: true
sellTokenBalance:
description: Where the sell token should be drawn from.
allOf:
- $ref: "#/components/schemas/SellTokenSource"
default: erc20
buyTokenBalance:
description: Where the buy token should be transferred to.
allOf:
- $ref: "#/components/schemas/BuyTokenDestination"
default: erc20
Comment thread
m-sz marked this conversation as resolved.
appData:
description: >
Full app data JSON string. Defaults to `"{}"` if omitted.
type: string
nullable: true
interactions:
description: Pre- and post-trade interactions for the order.
type: object
properties:
pre:
description: Interactions executed before the order's trade.
type: array
items:
$ref: "#/components/schemas/InteractionData"
post:
description: Interactions executed after the order's trade.
type: array
items:
$ref: "#/components/schemas/InteractionData"
required:
- sellToken
- buyToken
- sellAmount
- buyAmount
- kind
- owner
OrderSimulation:
description: >
The Tenderly simulation request for an order, along with any
Expand Down
5 changes: 5 additions & 0 deletions crates/orderbook/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ pub fn handle_all_routes(
"/api/v1/debug/simulation/{uid}",
get(debug_simulation::debug_simulation_handler),
),
(
"POST",
"/api/v1/debug/simulation",
post(debug_simulation::debug_simulation_post_handler),
),
// V2 routes
// /solver_competition routes (specific before parameterized)
(
Expand Down
Loading
Loading