Branchable preflight for capital-moving teams and agents

Simulate many futures before capital moves.

Determica turns proposed onchain actions and SQL checks into branchable EVM scenarios. Teams and agents run candidate routes and policy checks through deterministic forks, compare outcomes, and return evidence for revision, routing, approval, or signing.

Before the signature

Software can propose the transaction. The signer still owns the risk.

Actions are automated

Agents, bots, solvers, keepers, and workflows now generate routes, approvals, rebalances, and liquidations.

The signature is the gate

Before funds move, teams need deterministic evidence of what the action will touch, transfer, cost, and violate.

Determica preflights

Determica runs the candidate on pinned fork state, applies policy, and returns an approval-ready receipt.

Live demo: onchain preflight

Watch one onchain action become an evidence-backed signing decision.

Agents and teams submit candidate transactions, routes, or SQL policy checks. Determica pins live EVM state, forks executable futures, blocks policy failures, and returns the candidate to approve or the reason to revise. The notebook below preflights an ETH treasury allocation route, but the runtime is built for capital-moving actions before approval or signing.

Proposed action / Finalized-state forks / Candidate executions / Policy gates / Receipt-backed decision

1
-- Agent Treasury Signing Firewall preflight.
2
 
3
-- 1. Pin live mainnet state to a named local simulation.
4
SELECT evm_create_sim_at($transport, 'finalized', 'treasury_agent_preflight_base');
5
 
6
-- 2. Give the agent local funds and router approval.
7
-- These edits affect only the simulation, never mainnet.
8
WITH base AS (
9
SELECT MAX(sim_id) AS sim_id
10
FROM evm_simulations
11
WHERE name = 'treasury_agent_preflight_base'
12
)
13
SELECT evm_set_balance(base.sim_id, $agent_wallet, parse_ether(10))
14
FROM base;
15
 
16
WITH base AS (
17
SELECT MAX(sim_id) AS sim_id
18
FROM evm_simulations
19
WHERE name = 'treasury_agent_preflight_base'
20
)
21
SELECT evm_set_storage(
22
base.sim_id,
23
$weth_address,
24
evm_mapping_slot($agent_wallet, 3),
25
parse_ether(10)::BYTES32
26
)
27
FROM base;
28
 
29
WITH base AS (
30
SELECT MAX(sim_id) AS sim_id
31
FROM evm_simulations
32
WHERE name = 'treasury_agent_preflight_base'
33
)
34
SELECT evm_set_storage(
35
base.sim_id,
36
$weth_address,
37
evm_mapping_slot($swap_router_02_address, evm_mapping_slot($agent_wallet, 4)),
38
'0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'::BYTES32
39
)
40
FROM base;
41
 
42
-- 3. Define route templates to quote.
43
-- We quote these first so the final signable branch can use a live fork-derived minOut,
44
-- not a stale hard-coded price.
45
CREATE OR REPLACE TEMP TABLE route_templates AS
46
SELECT *
47
FROM (VALUES
48
(
49
1,
50
'direct_weth_usdc',
51
'canonical direct WETH -> USDC path',
52
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001f4A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'::BYTES
53
),
54
(
55
2,
56
'usdt_bridge_weth_usdc',
57
'repair route that crosses a denied stablecoin hop',
58
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc20001f4dAC17F958D2ee523a2206206994597C13D831ec7000064A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'::BYTES
59
)
60
) AS t(template_rank, template, hypothesis, path);
61
 
62
-- 4. Quote each template in an isolated branch with amountOutMinimum = 0.
63
-- These are not signable branches. They are measurement branches.
64
CREATE OR REPLACE TEMP TABLE quote_forks AS
65
SELECT
66
route_templates.*,
67
0::UINT256 AS amount_out_min,
68
forks.sim_id,
69
base.block_number AS eth_block
70
FROM route_templates
71
JOIN evm_simulations base
72
ON base.sim_id = evm_latest_sim('treasury_agent_preflight_base')
73
JOIN evm_fork_many(
74
evm_latest_sim('treasury_agent_preflight_base'),
75
[
76
{'scenario': 'quote_direct_weth_usdc'},
77
{'scenario': 'quote_usdt_bridge_weth_usdc'}
78
]
79
) AS forks
80
ON forks.scenario = 'quote_' || route_templates.template;
81
 
82
SELECT evm_prefetch_call(
83
route.sim_id,
84
$agent_wallet,
85
$swap_router_02_address,
86
encode_function_data(
87
$swap_router_02_abi,
88
'exactInput',
89
STRUCT_PACK(
90
path := route.path,
91
recipient := $agent_wallet,
92
amountIn := parse_ether(1),
93
amountOutMinimum := route.amount_out_min
94
)
95
)
96
)
97
FROM quote_forks route;
98
 
99
CREATE OR REPLACE TEMP TABLE quote_runs AS
100
SELECT
101
evm_execute_step(
102
route.sim_id,
103
$agent_wallet,
104
$swap_router_02_address,
105
encode_function_data(
106
$swap_router_02_abi,
107
'exactInput',
108
STRUCT_PACK(
109
path := route.path,
110
recipient := $agent_wallet,
111
amountIn := parse_ether(1),
112
amountOutMinimum := route.amount_out_min
113
)
114
),
115
0::UINT256,
116
1000000,
117
'storage'
118
) AS result,
119
route.*
120
FROM quote_forks route;
121
 
122
-- 5. Extract live quote evidence from the quote branches.
123
CREATE OR REPLACE TEMP TABLE route_quotes AS
124
WITH quote_windows AS (
125
SELECT
126
template_rank,
127
template,
128
hypothesis,
129
path,
130
sim_id,
131
eth_block,
132
(result).step_index AS step_index,
133
{
134
'sim_id': sim_id::UBIGINT,
135
'first_step_index': (result).step_index::UINTEGER,
136
'last_step_index': (result).step_index::UINTEGER,
137
'step_count': 1::UINTEGER,
138
'success': (result).success,
139
'gas_used': (result).gas_used::UBIGINT,
140
'trace_level': 'storage'
141
}::RUN AS run
142
FROM quote_runs
143
)
144
SELECT
145
template_rank,
146
template,
147
hypothesis,
148
path,
149
eth_block,
150
(run).success AS quote_success,
151
evm_run_amount_out(run, $agent_wallet::ADDRESS, $usdc_address::ADDRESS) AS quoted_out
152
FROM quote_windows
153
WHERE (run).success;
154
 
155
-- 6. Build the actual candidate signing set.
156
-- Each candidate executes in a fresh fork from the original base state.
157
CREATE OR REPLACE TEMP TABLE route_candidates AS
158
SELECT
159
1 AS route_rank,
160
'agent_original_stale_quote' AS candidate,
161
'agent used a stale quote; would revert before capital moves' AS hypothesis,
162
(quoted_out + parse_units(1, 6))::UINT256 AS amount_out_min,
163
9800::UBIGINT AS min_out_guard_bps,
164
path
165
FROM route_quotes
166
WHERE template = 'direct_weth_usdc'
167
 
168
UNION ALL
169
 
170
SELECT
171
2 AS route_rank,
172
'repair_denied_usdt_hop' AS candidate,
173
'repair executes but crosses a denied stablecoin contract' AS hypothesis,
174
(quoted_out * 9900 / 10000)::UINT256 AS amount_out_min,
175
9800::UBIGINT AS min_out_guard_bps,
176
path
177
FROM route_quotes
178
WHERE template = 'usdt_bridge_weth_usdc'
179
 
180
UNION ALL
181
 
182
SELECT
183
3 AS route_rank,
184
'repair_zero_minout' AS candidate,
185
'repair executes but is unsafe because amountOutMinimum is zero' AS hypothesis,
186
0::UINT256 AS amount_out_min,
187
9800::UBIGINT AS min_out_guard_bps,
188
path
189
FROM route_quotes
190
WHERE template = 'direct_weth_usdc'
191
 
192
UNION ALL
193
 
194
SELECT
195
4 AS route_rank,
196
'repair_signable_guarded' AS candidate,
197
'direct route with live quote-derived slippage guard' AS hypothesis,
198
(quoted_out * 9900 / 10000)::UINT256 AS amount_out_min,
199
9800::UBIGINT AS min_out_guard_bps,
200
path
201
FROM route_quotes
202
WHERE template = 'direct_weth_usdc';
203
 
204
CREATE OR REPLACE TEMP TABLE route_forks AS
205
SELECT
206
route_candidates.*,
207
forks.sim_id,
208
base.block_number AS eth_block
209
FROM route_candidates
210
JOIN evm_simulations base
211
ON base.sim_id = evm_latest_sim('treasury_agent_preflight_base')
212
JOIN evm_fork_many(
213
evm_latest_sim('treasury_agent_preflight_base'),
214
[
215
{'scenario': 'agent_original_stale_quote'},
216
{'scenario': 'repair_denied_usdt_hop'},
217
{'scenario': 'repair_zero_minout'},
218
{'scenario': 'repair_signable_guarded'}
219
]
220
) AS forks
221
ON forks.scenario = route_candidates.candidate;
222
 
223
-- 7. Execute every candidate branch.
224
-- Quote prefetches warmed the shared chain state; candidate executions can reuse
225
-- cached route state and lazily load any remaining slots.
226
-- Failed branches are still recorded as evidence.
227
CREATE OR REPLACE TEMP TABLE route_runs AS
228
SELECT
229
evm_execute_step(
230
route.sim_id,
231
$agent_wallet,
232
$swap_router_02_address,
233
encode_function_data(
234
$swap_router_02_abi,
235
'exactInput',
236
STRUCT_PACK(
237
path := route.path,
238
recipient := $agent_wallet,
239
amountIn := parse_ether(1),
240
amountOutMinimum := route.amount_out_min
241
)
242
),
243
0::UINT256,
244
1000000,
245
'storage'
246
) AS result,
247
route.*
248
FROM route_forks route;
249
 
250
-- 8. Score branches with execution, swap-event evidence, policy, slippage guard, and receipt hash.
251
WITH run_windows AS (
252
SELECT
253
route_rank,
254
candidate,
255
hypothesis,
256
sim_id,
257
eth_block,
258
amount_out_min,
259
min_out_guard_bps,
260
(result).step_index AS step_index,
261
{
262
'sim_id': sim_id::UBIGINT,
263
'first_step_index': (result).step_index::UINTEGER,
264
'last_step_index': (result).step_index::UINTEGER,
265
'step_count': 1::UINTEGER,
266
'success': (result).success,
267
'gas_used': (result).gas_used::UBIGINT,
268
'trace_level': 'storage'
269
}::RUN AS run
270
FROM route_runs
271
),
272
swap_logs AS (
273
SELECT
274
run_windows.candidate,
275
COUNT(*) AS swap_event_count
276
FROM run_windows
277
JOIN evm_step_logs logs
278
ON logs.sim_id = run_windows.sim_id
279
AND logs.step_index = run_windows.step_index
280
WHERE logs.topic0 = '0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67'::BYTES32
281
AND (run_windows.run).success
282
GROUP BY run_windows.candidate
283
),
284
scored AS MATERIALIZED (
285
SELECT
286
run_windows.route_rank,
287
run_windows.candidate,
288
run_windows.hypothesis,
289
run_windows.eth_block,
290
run_windows.amount_out_min,
291
run_windows.min_out_guard_bps,
292
(run_windows.run).success AS execution_success,
293
(run_windows.run).gas_used AS gas_used,
294
COALESCE(
295
evm_run_amount_out(run_windows.run, $agent_wallet::ADDRESS, $usdc_address::ADDRESS),
296
0::UINT256
297
) AS amount_out,
298
COALESCE(swap_logs.swap_event_count, 0) AS swap_event_count,
299
evm_run_touched_contract_count(run_windows.run) AS touched_contracts,
300
evm_run_policy_result(run_windows.run, $route_policy::JSON) AS policy_result,
301
run_windows.run
302
FROM run_windows
303
LEFT JOIN swap_logs ON swap_logs.candidate = run_windows.candidate
304
),
305
decision_rows AS (
306
SELECT
307
route_rank,
308
candidate,
309
eth_block,
310
execution_success,
311
CASE
312
WHEN execution_success THEN format_units(amount_out, 6)
313
ELSE '0.000000'
314
END AS usdc_out,
315
gas_used,
316
swap_event_count,
317
COALESCE(json_extract(policy_result, '$.denied_contracts.count')::UINTEGER, 0) AS denied_contract_count,
318
CASE
319
WHEN NOT execution_success THEN 'n/a'
320
WHEN amount_out_min = 0::UINT256 THEN 'none'
321
WHEN amount_out > 0::UINT256 THEN '99%'
322
ELSE 'n/a'
323
END AS guard_policy,
324
CASE
325
WHEN NOT execution_success THEN 'would revert if signed'
326
WHEN evm_policy_has_failures(policy_result) THEN evm_policy_failure_summary(policy_result)
327
WHEN swap_event_count = 0 THEN 'no swap evidence'
328
WHEN amount_out_min * 10000 < amount_out * min_out_guard_bps::UINT256 THEN 'slippage guard too loose'
329
ELSE 'signing packet ready'
330
END AS reason,
331
evm_run_receipt_hash(run, policy_result) AS receipt_hash,
332
CASE
333
WHEN execution_success
334
AND NOT evm_policy_has_failures(policy_result)
335
AND swap_event_count > 0
336
AND amount_out_min * 10000 >= amount_out * min_out_guard_bps::UINT256
337
THEN 0
338
ELSE 1
339
END AS sort_bucket
340
FROM scored
341
)
342
SELECT
343
CASE WHEN sort_bucket = 0 THEN 'PASS' ELSE 'REJECT' END AS decision,
344
candidate AS route,
345
usdc_out,
346
reason,
347
eth_block,
348
'gas=' || gas_used::VARCHAR
349
|| ' swaps=' || swap_event_count::VARCHAR
350
|| ' denied=' || denied_contract_count::VARCHAR
351
|| ' guard=' || guard_policy
352
|| ' receipt=' || substr(receipt_hash::VARCHAR, 1, 8) || '...' || right(receipt_hash::VARCHAR, 5)
353
AS evidence
354
FROM decision_rows
355
ORDER BY sort_bucket ASC, route_rank ASC;
Notebook ready in readonly mode.

The runtime contract

Every capital-moving intent becomes an inspectable SQL plan.

The live notebook above is one interface; an agent API is another. Whether the SQL is produced by an agent workflow or written by a human, Determica makes the plan reviewable before it runs: fork EVM state, execute candidate branches, apply policy checks, and return receipt-backed evidence before approval or signing.

Not a dashboard. Not a chatbot. Not a one-off transaction preview. Determica is the repeatable runtime where onchain intent becomes verifiable pre-signing execution.

A Determica run

Intent

Human request, agent route, bot candidate, or policy objective.

SQL plan

Generated or written SQL that can be reviewed before execution.

Run

Pin state, fork futures, execute branches.

Decide

Return rejected paths, selected action, and receipt evidence.

Inspectable SQL

1
WITH candidate_forks AS (
2
SELECT c.*, f.sim_id
3
FROM candidate_routes c
4
JOIN evm_fork_many(
5
evm_latest_sim('agent_preflight'),
6
$candidate_scenarios
7
) f ON f.scenario = c.candidate
8
),
9
runs AS (
10
SELECT
11
candidate,
12
evm_execute_candidate(
13
sim_id,
14
$agent_wallet,
15
target,
16
calldata,
17
0::UINT256,
18
30000000::UBIGINT,
19
'storage'
20
) AS run
21
FROM candidate_forks
22
),
23
scored AS (
24
SELECT
25
candidate,
26
evm_run_policy_result(run, $preflight_policy::JSON) AS policy_result,
27
run
28
FROM runs
29
)
30
SELECT
31
candidate,
32
CASE
33
WHEN evm_policy_has_failures(policy_result)
34
THEN 'REJECT: ' || evm_policy_failure_summary(policy_result)
35
ELSE 'PASS: signing packet ready'
36
END AS decision,
37
evm_run_receipt_hash(run, policy_result) AS receipt_hash
38
FROM scored;
candidate result evidence
agent_original_stale_quote REJECT would revert if signed
repair_denied_usdt_hop REJECT denied contract
repair_zero_minout REJECT missing guard
repair_signable_guarded PASS signing packet ready

One product loop

One decision path for humans, bots, agents, and approval workflows.

Review -> Run -> Evidence

01 / Intent

Ask or propose

Human request, agent route, bot candidate, or policy objective.

02 / Plan

Inspect the SQL

Generated or written SQL that can be reviewed before execution.

03 / Fork

Run futures

Pin EVM state, fork candidates, execute branches.

04 / Decide

Pass, fail, or revise

Reject unsafe paths and return the candidate allowed to continue.

05 / Evidence

Attach proof

Return tables, policy output, selected action, rejected futures, and receipt evidence.

Pilot conversations

Bring the workflow you already preflight manually.

We are speaking with teams that move or control onchain capital and already rely on scripts, fork simulations, notebooks, risk vendors, or internal checks before signing.

Design partners, operators, and investors can reach out with a workflow, thesis, or introduction.

Useful context: the repeated action, today's preflight path, and the evidence a signer needs before approval.

Prefer to write directly? Email [email protected].

Pilot intake

Tell us what you preflight. This opens a prefilled email draft you can edit before sending.