EIP-7702
BOT Chain Mainnet y Testnet admiten transacciones EIP-7702 de tipo 4. Una EOA existente puede firmar una autorización que delega su código de ejecución en una implementación de cuenta desplegada, conservando la dirección EOA original, el saldo y el control de la clave privada.
Existen dos rutas de envío:
- Transacción nativa: envía una transacción de tipo 4 que contenga
authorizationListmediante el RPC de la cadena. - UserOperation: el Bundler de BOT Chain no admite actualmente UserOperations EIP-7702. Esta ruta puede implementarse con un Bundler propio.
Transacciones nativas de tipo 4
La ruta nativa no utiliza EntryPoint ni Bundler. La EOA paga el Gas de la transacción.
1. Instalar dependencias
npm install viem
2. Crear los clientes
Este ejemplo utiliza 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"),
});
No guardes nunca una clave privada en el código fuente del frontend en producción. Usa un conector de monedero o un servicio de firma protegido.
3. Firmar la autorización y establecer la delegación
Cuando la EOA es tanto la firmante de la autorización como la remitente de la transacción de tipo 4, establece executor: "self" para que viem gestione correctamente la relación entre el nonce de la transacción y el de la autorización.
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 construye y envía una transacción EIP-7702 de tipo 4.
Si la implementación de la cuenta requiere inicialización, incluye el calldata de inicialización en la misma transacción:
import { encodeFunctionData } from "viem";
const initializeData = encodeFunctionData({
abi: accountAbi,
functionName: "initialize",
args: [/* argumentos de inicialización */],
});
const hash = await walletClient.sendTransaction({
account: eoa,
authorizationList: [authorization],
to: eoa.address,
data: initializeData,
});
4. Verificar la delegación
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. Llamar a la cuenta delegada
Después de la delegación, las llamadas siguen dirigiéndose a la dirección EOA. Codifica el calldata según el ABI de la implementación de la cuenta.
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,
});
El destino de negocio es target. La implementación de la cuenta continúa siendo la dirección implementation autorizada anteriormente.