Skip to content

Recipes

Small snippets for the cases where you need to deviate from the Quickstart defaults.

SelfInstaller::install covers 99% of cases — it runs the pre-flight, sends the tx, and on Arbitrum-style "intrinsic gas too low" / "gas uint64 overflow" errors retries once with an explicit 100k gas limit.

When you need more control — a sponsored relay, explicit gas pricing, inspecting the tx before it goes out — use prepare_install_tx. It returns the fully-assembled EIP-7702 type-4 TransactionRequest without sending:

use alloy_network::TransactionBuilder;
use alloy_provider::Provider;
use trident_evm_aa::eip7702_installer::SelfInstaller;
let tx = SelfInstaller::new()
.prepare_install_tx(&provider, &signer)
.await?;
// Example: skip the auto-retry and set the gas limit yourself.
let pending = provider
.send_transaction(tx.with_gas_limit(100_000))
.await?;

prepare_install_tx still does everything install does up to the send: authority-vs-provider-signer check, on-chain code check, auto-deploy of TridentAccount at the canonical address, chain-id + nonce fetch, authorization signing. Only the submission path is yours to own.

MulticallBuilder::send_with_wallet_provider covers the common case — a ProviderBuilder::new().wallet(...) provider whose default signer is the 7702-delegated EOA. For a sponsored relay, explicit gas/fee/nonce control, or inspecting the tx before it goes out, use build_transaction_request. It mirrors SelfInstaller::prepare_install_tx: returns the fully-assembled outer execute(Multicall3, aggregate3Value(...)) request without sending.

use alloy_network::{AnyNetwork, TransactionBuilder};
use alloy_provider::Provider;
use trident_evm_aa::call_builder::MulticallBuilder;
let tx = MulticallBuilder::new()
.call(/* ... */)
.build_transaction_request::<AnyNetwork>(eoa);
let pending = provider
.send_transaction(tx.with_gas_limit(300_000))
.await?;

tx_signer is the EOA that will sign the outer transaction; it is set as the request’s to (self-call) and must be 7702-delegated to TridentAccount at send time. value is set to the sum of per-call values. Gas, fees, and nonce are left unset so callers can own the submission path.

If you have a plain Provider without a wallet but know the delegated EOA, builder.send(provider, tx_signer) is the middle form — builds and sends in one call, same as send_with_wallet_provider, but with the signer passed explicitly.

use alloy_primitives::address;
use trident_evm_aa::eip7702_installer::SelfInstaller;
SelfInstaller::new()
.with_target(address!("YourCustomAccountImpl"))
.install(provider, &signer)
.await?;

with_target overrides the EIP-7702 delegation target. Custom targets are not auto-deployed — if the bytecode isn’t already on-chain, install returns InstallError::TridentAccountNotDeployed.

SelfInstaller::new()
.without_deploy_if_missing()
.install(provider, &signer)
.await?;

The default installer auto-deploys TridentAccount at the canonical address via Arachnid’s CREATE2 proxy if it isn’t there yet. Use without_deploy_if_missing() to require the bytecode be pre-deployed — install returns InstallError::TridentAccountNotDeployed if it isn’t.

use alloy_primitives::address;
use trident_evm_aa::call_builder::MulticallBuilder;
MulticallBuilder::new()
.with_multicall3(address!("YourMulticall3"))
// ...append calls, send...

Use this only when the canonical 0xcA11bde05977b3631167028862bE2a173976CA11 isn’t on your chain, or in local tests with a custom deployment. The default is canonical Multicall3.

Manually deploy TridentAccount on a new chain

Section titled “Manually deploy TridentAccount on a new chain”
use alloy_primitives::B256;
use trident_evm_aa::deployer;
let addr = deployer::deploy_deterministic(&provider, B256::ZERO).await?;
// `addr` == DEFAULT_ADDRESS on any chain with Arachnid's CREATE2 proxy.

Rarely needed — the default installer flow auto-deploys for you. Reach for this when you want to pre-deploy on a brand-new network or in a deployment pipeline. predict_deterministic_address(salt) computes the address off-chain without sending a transaction.