Skip to content

Trident EVM Multicall

Trident EVM Multicall turns your EOA into a minimal smart account that batches any combination of EVM calls into a single atomic transaction — no new wallet, no bundler, no paymaster.

It is one ~30-line contract, TridentAccount, living at the canonical CREATE2 address 0x319A60309bA63b73624729Cc903CD6FeE78af696 on every EVM chain with the Arachnid proxy. It exposes one function — execute(target, data) — that delegatecalls target as your account. You pick target per transaction: Multicall3 to batch, a session-key module, a signature policy, whatever you want.

Who it’s for: EVM devs who need atomic batched actions — approve + swap + deposit, wrap + transfer + send, deposit + settle — from their existing EOA.

  1. Install once. Sign an EIP-7702 authorization that tells the chain: “when anyone calls my EOA, run TridentAccount’s code in my context.” After the tx confirms, your EOA is a TridentAccount — same balance, same storage, same address, plus one new function you can call.
  2. Call yourself. Send a transaction to your own address with calldata execute(target, data). Because msg.sender == address(this), the NotSelf guard passes; from anyone else it reverts.
  3. Pick a module per transaction. execute delegatecalls target with data. The target’s code runs as your account — reads and writes your storage, spends from your balance, and its sub-calls appear to come from your EOA. Set target = Multicall3 and pack N calls into data to batch; point at a different module tomorrow for different behavior, no redeploy.

The whole thing, verbatim. One function plus a receive():

// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
contract TridentAccount {
error NotSelf();
function execute(address target, bytes calldata data) external payable returns (bytes memory) {
if (msg.sender != address(this)) revert NotSelf();
(bool ok, bytes memory ret) = target.delegatecall(data);
if (!ok) {
assembly {
revert(add(ret, 0x20), mload(ret))
}
}
return ret;
}
receive() external payable {}
}
  • The NotSelf guard is the entire authorization model. Under EIP-7702, msg.sender == address(this) only holds for a tx the EOA owner signed to their own address.
  • Delegatecall failures bubble the original revert data up unchanged, so MulticallBuilder errors surface the underlying sub-call’s reason.
  • receive() exists so the authority can accept ETH and so the envelope of the 7702 self-install tx (empty calldata) doesn’t revert on the delegated authority.
  • Only you can trigger your account. execute reverts unless msg.sender == address(this). Under EIP-7702, that only passes for a transaction you signed and sent to your own address — no relayer, no external caller, no malicious contract.
  • Nothing to take over. No owner, no admin, no initializer, no upgrade hook, no state anyone could claim. A bytecode-identical copy on another chain has nothing to steal.
  • No hidden surface. Exactly two entry points: execute (gated) and receive() (accept ETH).
  • Module risk is your choice. TridentAccount trusts target because you picked it. Delegatecalling a malicious module carries the same risk any smart account has when authorizing arbitrary code — the account doesn’t add or remove that risk. MulticallBuilder defaults to canonical Multicall3.
  • No custom crypto. Authorization is the EVM’s own EIP-7702 signing. There is no signature logic inside the account.

The trident-evm-aa Rust crate gives you three things and nothing else:

  • SelfInstaller — install the 7702 delegation on your EOA (auto-deploys TridentAccount at the canonical address if the chain doesn’t have it yet).
  • MulticallBuilder — compose sub-calls and send them as one execute(Multicall3, aggregate3Value(...)) transaction.
  • deployer — place TridentAccount at its canonical address via Arachnid’s CREATE2 proxy, if you ever need to do it manually.

Continue to the SDK Quickstart.