Saltar al contenido principal

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 authorizationList mediante 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.