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.
How it works
Section titled “How it works”- 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 aTridentAccount— same balance, same storage, same address, plus one new function you can call. - Call yourself. Send a transaction to your own address with calldata
execute(target, data). Becausemsg.sender == address(this), theNotSelfguard passes; from anyone else it reverts. - Pick a module per transaction.
executedelegatecallstargetwithdata. 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. Settarget = Multicall3and pack N calls intodatato batch; point at a different module tomorrow for different behavior, no redeploy.
The contract
Section titled “The contract”The whole thing, verbatim. One function plus a receive():
// SPDX-License-Identifier: MITpragma 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
NotSelfguard 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
MulticallBuildererrors 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.
Security
Section titled “Security”- Only you can trigger your account.
executereverts unlessmsg.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) andreceive()(accept ETH). - Module risk is your choice.
TridentAccounttruststargetbecause 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.MulticallBuilderdefaults 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-deploysTridentAccountat the canonical address if the chain doesn’t have it yet).MulticallBuilder— compose sub-calls and send them as oneexecute(Multicall3, aggregate3Value(...))transaction.deployer— placeTridentAccountat its canonical address via Arachnid’s CREATE2 proxy, if you ever need to do it manually.
Continue to the SDK Quickstart.