0x0903 and a companion plugin in the wasm keeper form a bidirectional bridge between the two runtimes. Solidity contracts can execute and query CosmWasm contracts, and CosmWasm contracts can call and query EVM contracts.
This page covers phase 1 of the bridge, which is what ships today. The EVM is live on testnet (lumera-testnet-2) only. Mainnet runs v1.12.0 and gains the EVM with its upgrade.
The two directions
Both directions share a reentrancy guard and execute as the calling contract, not as the outer user.
What phase 1 covers
Phase 1 supports non-payable calls in both directions.- From the EVM you get
execute,query,contractInfo, andrawQueryagainst any CosmWasm contract. - From CosmWasm you get
evm_callmessages and queries plus anevm_accountquery. - No funds move across the boundary.
executeis non-payable andevm_callcarries no value field. - No instantiation. You cannot deploy a CosmWasm contract from the EVM or an EVM contract from CosmWasm.
- The reentrancy guard enforces a maximum call depth of 1, so a call cannot cross the boundary twice (no EVM to Wasm to EVM chains).
- Every CosmWasm to EVM call is capped at 3,000,000 gas or the remaining gas, whichever is smaller.
EVM to CosmWasm
The interface below comes fromIWasm.sol in the lumera repo.
IWasm.sol
Example
WasmCaller.sol
CosmWasm to EVM
CosmWasm contracts reach the EVM through the standardCustom envelope. No precompile address is involved in this direction.
To call an EVM contract, send a CosmosMsg::Custom with an evm_call payload.
contract field is the hex EVM contract address. The calldata field is hex-encoded EVM calldata, meaning the function selector plus ABI-encoded arguments. Phase 1 has no value field.
To read EVM state, send a QueryRequest::Custom with the same evm_call shape. It behaves like eth_call and returns the hex-encoded return data.
evm_account query returns basic account info for any EVM address.
Behavior you should know
- Sender identity. Cross-runtime calls execute as the calling contract, never as the transaction origin. An EVM contract calling
executeappears to the CosmWasm side as its own address converted to bech32. A CosmWasm contract callingevm_callappears to the EVM side as its own address, somsg.senderin the target contract is the wasm contract. Proxy and delegatecall patterns do not propagate across the runtime boundary. - Atomicity. Failures revert atomically. An EVM to Wasm call snapshots both the multistore and the EVM state journal, and both revert together on failure. A Wasm to EVM call runs in a cache context that the dispatcher discards on failure.
- Gas. Both runtimes settle in Cosmos SDK gas. An EVM to Wasm call deducts the consumed Cosmos gas from the calling contract’s gas. A Wasm to EVM call charges the EVM gas used back to the wasm context, capped at 3,000,000 per call.
- Events. Successful
executecalls emit aWasmExecutedEVM log with the caller, the target contract address, and the raw response.
app/wasm_evm_plugin.go in the lumera repo.
Next steps
Precompiles overview
The full address map and when to use each precompile.
Action precompile
Drive Cascade and Sense actions from Solidity.
Deploy with Remix
Deploy and test a contract against Lumera testnet.