跳到主要内容

EIP-7702

BotChain 主网和测试网支持 EIP-7702 type 4 交易。已有 EOA 可以签署授权,把自己的执行代码委托给一份已部署的账户实现,同时保留原 EOA 地址、余额和私钥控制权。

支持分为两条调用路径:

  • 原生交易:通过链 RPC 发送包含 authorizationList 的 type 4 交易。

  • UserOperation:暂不支持通过BOT Chain Bundler提交7702模式的UserOperation,可在自建Bundler实现

原生 type 4 交易​

原生路径不经过 EntryPoint 和 Bundler。EOA 自己支付交易 Gas。

1. 安装依赖​

npm i viem

2. 创建客户端​

以下示例使用测试网:

import {
createPublicClient,
createWalletClient,
http,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";

const botTestnet = {
id: 968,
name: "BotChain 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"),
});

生产环境不要在前端源码中保存私钥,应使用钱包连接器或受保护的签名服务。

3. 签署授权并设置委托​

当 EOA 同时是授权签名者和 type 4 交易发送者时,必须设置 executor: "self",由 viem 正确处理交易 nonce 与授权 nonce 的关系。

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 会构造并提交 EIP-7702 type 4 交易。

如果账户实现需要初始化,把初始化 calldata 放进同一笔交易:

import { encodeFunctionData } from "viem";

const initializeData = encodeFunctionData({
abi: accountAbi,
functionName: "initialize",
args: [/* 初始化参数 */],
});

const hash = await walletClient.sendTransaction({
account: eoa,
authorizationList: [authorization],
to: eoa.address,
data: initializeData,
});

4. 验证委托结果​

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. 调用委托账户​

委托生效后,调用地址仍然是 EOA,calldata 按账户实现的 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,
});

业务目标地址是 target,账户实现地址仍是之前授权的 implementation。