# trident-evm-aa
Rust helpers for deploying the Trident smart account, installing it on your EOA via EIP-7702, and batching transactions through it. See the [repo README](../../README.md) for the overall design.
## Modules
- **`abi`** — `sol!` bindings for `TridentAccount` (built from a committed artifact in `artifacts/`) and an inline `Multicall3` interface.
- **`deployer`** — `deploy`, `deploy_deterministic`, `predict_deterministic_address`, `CREATE2_FACTORY`, `DeployError`.
- **`eip7702_installer`** — `SelfInstaller` (builder: `new`, `with_target`, `prepare_install_tx`, `prepare_install_tx_unchecked`, `install`, `install_unchecked`), `DEFAULT_TARGET`, `InstallError` (includes `AuthorityMismatch`).
- **`call_builder`** — `MulticallBuilder` (builder: `new`, `with_multicall3`, `call`, `call_with_value`, `send_value`, `total_value`, `aggregate3_calldata`, `execute_call_calldata`, `build_transaction_request`, `send`, `send_with_wallet_provider`), `MULTICALL3`, `MulticallError`.
## Typical usage
```rust
use trident_evm_aa::{
call_builder::MulticallBuilder,
deployer,
eip7702_installer::SelfInstaller,
};
// 1. Put TridentAccount on the chain (rarely — usually once per chain, same
// address everywhere thanks to Arachnid's CREATE2 proxy).
let account_impl = deployer::deploy_deterministic(provider.clone(), salt).await?;
// 2. Install the 7702 delegation on the signer's EOA.
SelfInstaller::new()
.with_target(account_impl)
.install(provider.clone(), &signer)
.await?;
// 3. Batch operations — each sub-call runs as the EOA.
MulticallBuilder::new()
.call_with_value(weth, &IWETH::depositCall {}, amount)
.send_value(recipient, value)
.send_with_wallet_provider(provider)
.await?;
```
For runnable end-to-end programs, see `examples/`.
## Requirements
- Rust 1.86+ (workspace MSRV).
- alloy 1.8.x ecosystem (workspace-pinned versions).
Consumers need nothing else — the TridentAccount ABI + bytecode ships inside the crate at `artifacts/TridentAccount.sol/TridentAccount.json`. Contributors rebuilding the contract must re-run `just evm-build` at the workspace root, which refreshes both `contracts/out/` and the crate-local copy; a CI drift check enforces the two stay in sync.
## Gotchas
- **`SelfInstaller` is self-install only.** The `authority` you pass must match the provider's `default_signer_address()` — EIP-7702 nonce arithmetic depends on it. Mismatches fail fast with `InstallError::AuthorityMismatch` instead of silently producing a stuck tx.
- **Nonce cache drifts after a 7702 install.** The applied authorization bumps the authority's on-chain nonce an extra time, which alloy's default `CachedNonceManager` doesn't track. If you plan to send more txs from the same provider after install, build it with `ProviderBuilder::with_simple_nonce_management()` or pass explicit per-tx nonces. `test_util::TestSetup::provider()` uses `SimpleNonceManager` for this reason.
- **`MulticallBuilder::send` / `send_with_wallet_provider` send `msg.value = sum(per-call values)`.** Multicall3's `aggregate3Value` enforces `msg.value == valAccumulator`. Since sender == receiver (self-call), the transfer is a net-zero balance movement — but the EOA must hold at least that much ETH to pass the EVM's pre-execution balance check. It's an accounting artifact of Multicall3's invariant, not extra cost.
- **`send` vs `send_with_wallet_provider`.** Use `send_with_wallet_provider` when your provider was built with `.wallet(signer)` — it reads the default signer and treats that EOA as both the outer tx's `from` and `to`. Use `send(provider, tx_signer)` when you need to name the signing EOA explicitly (e.g. multi-wallet providers, sponsored relays, or when driving `build_transaction_request` yourself). In both cases `tx_signer` must be 7702-delegated to `TridentAccount`.
## Testing
```bash
cargo test -p trident-evm-aa
```
Requires `anvil` on `$PATH` (Foundry provides it). `test_util::TestSetup` spawns a Prague-hardfork anvil per test and pre-injects mainnet runtime bytecodes for Multicall3, WETH9, and the Arachnid CREATE2 proxy.