@eez:on
Evaluate an expression as if the script were on another chain, and return its value: helpers, :: calls, variables and arithmetic resolve against that chain (reads only).
On-chain (@eez:on!): Reads the other chain through the proxy of its Assertions core, so the assertion runs as a transaction; one hop only, not simulable.
⚗️ Experimental — available at next.evmcrispr.com.
Returns: any
Syntax
Section titled “Syntax”@eez:on(chain expression)Arguments
Section titled “Arguments”| Name | Type | Description |
|---|---|---|
chain | chain | Chain to evaluate on (eezL2, a viem name or a chain id) |
expression | any | Expression evaluated as if the script had switched to that chain |
Examples
Section titled “Examples”# From L1, read the connected account's balance on the rollupswitch eezL1print @eez:on(eezL2 @balance(ETH @me))- The expression runs with the script's client switched to the target chain and the previous client restored afterwards — inside a
sim:forkthe fork is kept. Everything inside resolves against the target chain:@balance,@token:balance,::reads, other modules' helpers (e.g.@eez:proxycomputes the proxy on that chain), nested@eez:on. - Read-only by construction: helpers cannot emit actions, so
exec-style writes are not possible inside the expression. Use the eez:on command to write. - Module config variables (
$eez:registry,$std:tokenlist, …) are global, not per chain: a valuesetfor the script's own chain is also seen while evaluating on the other one. - Editor completions inside the expression assume the script's current chain, not the target.
- This is the off-chain face. The on-chain face (
@eez:on!, usable insideassertfor a synchronous cross-rollup read) needs the on-chain helper runtime deployed on the target rollup and is not available yet.
On-chain face (@eez:on!)
Section titled “On-chain face (@eez:on!)”A synchronous cross-rollup read inside an assertion. The inner expression compiles as if the script were on the other chain (so @balance!, :: reads and every nested on-chain helper resolve there), and is evaluated at assertion time through this chain's cross-chain proxy of the Assertions core deployed over there: a static call the EEZ sequencer composes, returning the remote value inline.
switch eezL1assert @eez:on!(eezL2 @balance!(ETH @me)) >= 1e18 "not enough on the rollup"- The assertion becomes a transaction. Only a transaction reaches the composer; an
eth_callthrough a proxy always fails with a registry gate error (ExecutionNotInCurrentBlock, orExecutionNotFound()). Inside abatchit already is one. It cannot be simulated insim:fork, since a fork has no composer. - Two proxies of the Assertions core must exist first: the remote core's proxy on this chain (
eez:deploy-proxy 0x67DBB438FdC614466984Dc8F68dAB812d785a2aE --chain eezL2from L1), which the read goes out through, and this chain's core's proxy over there (the same command from L2 with--chain eezL1), which the other side sees as the reader. A static read cannot create a proxy on the way, so a missing one gets the transaction evicted rather than reverted. @mecompiles to the literal wallet address, so@balance!(ETH @me)on the rollup is the wallet's balance there. Anything on the far side that looks atmsg.sendersees the proxy of the caller instead.- One hop only: the devnet composes a static read across one chain boundary, not
@eez:on!inside@eez:on!. - A constant inner expression is folded at composition time and never crosses;
@eez:on!(eezL1 …)from L1 is just the inner expression.
See Also
Section titled “See Also”- eez:on — run a block of commands on the other rollup atomically