EIP-7702
BOT Chain Mainnet and Testnet support EIP-7702 type 4 transactions. An existing EOA can sign an authorization that delegates its execution code to a deployed account implementation while retaining the original EOA address, balance, and private-key control.
Two submission paths exist:
- Native transaction: Send a type 4 transaction containing
authorizationListthrough the chain RPC. - UserOperation: The BOT Chain Bundler does not currently support EIP-7702 UserOperations. This path can be implemented with a self-hosted Bundler.
Native type 4 transactions
The native path does not use EntryPoint or a Bundler. The EOA pays the transaction Gas.
1. Install dependencies
npm install viem
2. Create clients
This example uses BOT Chain Testnet:
import {
createPublicClient,
createWalletClient,
http,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
const botTestnet = {
id: 968,
name: "BOT Chain Testnet",
nativeCurrency: {
name: "BOT",
symbol: "BOT",
decimals: 18,
},
rpcUrls: {
default: {
http: ["https://rpc.bohr.life"],
},
},
} as const;
const eoa = privateKeyToAccount("0x...");
const publicClient = createPublicClient({
chain: botTestnet,
transport: http("https://rpc.bohr.life"),
});
const walletClient = createWalletClient({
account: eoa,
chain: botTestnet,
transport: http("https://rpc.bohr.life"),
});
Never store a private key in frontend source code in production. Use a wallet connector or a protected signing service.
3. Sign the authorization and set the delegation
When the EOA is both the authorization signer and the type 4 transaction sender, set executor: "self" so that viem handles the relationship between the transaction nonce and authorization nonce correctly.
const implementation = "0x..." as const;
const authorization = await walletClient.signAuthorization({
account: eoa,
contractAddress: implementation,
executor: "self",
});
const hash = await walletClient.sendTransaction({
account: eoa,
authorizationList: [authorization],
to: eoa.address,
data: "0x",
});
await publicClient.waitForTransactionReceipt({ hash });
sendTransaction constructs and submits an EIP-7702 type 4 transaction.
If the account implementation requires initialization, include the initialization calldata in the same transaction:
import { encodeFunctionData } from "viem";
const initializeData = encodeFunctionData({
abi: accountAbi,
functionName: "initialize",
args: [/* initialization arguments */],
});
const hash = await walletClient.sendTransaction({
account: eoa,
authorizationList: [authorization],
to: eoa.address,
data: initializeData,
});
4. Verify the delegation
const code = await publicClient.getCode({
address: eoa.address,
});
const expectedCode =
`0xef0100${implementation.slice(2).toLowerCase()}`;
if (code?.toLowerCase() !== expectedCode) {
throw new Error("EIP-7702 delegation was not applied");
}
5. Call the delegated account
After delegation, calls still target the EOA address. Encode calldata according to the account implementation's ABI.
import { encodeFunctionData } from "viem";
const callData = encodeFunctionData({
abi: accountAbi,
functionName: "execute",
args: [
target,
value,
targetCallData,
],
});
const hash = await walletClient.sendTransaction({
account: eoa,
to: eoa.address,
data: callData,
});
The business target is target. The account implementation remains the previously authorized implementation address.