EVM (Ethereum)

EVM Transactions

Build, sign, broadcast, and monitor EVM transactions with Zafeguard components.

EVM Transactions

Components for the full EVM transaction lifecycle: calldata encoding → transaction building → signing → broadcasting → confirmation.

Public RPC URLs enforce rate limits per IP address and can fail under concurrent load. Use a private endpoint (Alchemy, Infura, QuickNode, or self-hosted). See Connecting to any chain.


BUILD_EVM_CALLDATA

BUILD_EVM_CALLDATA Workflow Component

ABI-encode a contract function call into hex calldata.

Config

FieldTypeRequiredDescription
functionNamestringYesName of the contract function to encode (e.g. "transfer")

Inputs

FieldTypeDescription
abiAbiItem[]Contract ABI (array of function/event definitions)
argsstring[]Function arguments in order, as strings

Outputs

FieldTypeDescription
calldatastringABI-encoded hex calldata (0x...)

SDK example

import { WorkspaceClient, ComponentModule } from '@zafeguard/caller-sdk';
const workspace = new WorkspaceClient({ apiKey: process.env.ZAFEGUARD_API_KEY! });

const result = await workspace.call(ComponentModule.BUILD_EVM_CALLDATA, {
  abi: [
    {
      type: 'function',
      name: 'transfer',
      inputs: [
        { name: 'to', type: 'address' },
        { name: 'amount', type: 'uint256' },
      ],
      outputs: [{ name: '', type: 'bool' }],
      stateMutability: 'nonpayable',
    },
  ],
  args: ['0xRecipientAddress', '1000000'],
}).promise();
console.log(result.calldata); // "0xa9059cbb..."

BUILD_EVM_TRANSFER_CALLDATA

BUILD_EVM_TRANSFER_CALLDATA Workflow Component

Convenience wrapper around BUILD_EVM_CALLDATA for the common case of sending native ETH or an ERC-20 transfer. Picks the right encoding automatically:

  • tokenAddress is null → native ETH transfer. Returns calldata: "0x", to: recipient, value: amount.
  • tokenAddress set → ERC-20 transfer(recipient, amount). Returns the encoded calldata, to: tokenAddress, value: "0x0".

The output plugs directly into BUILD_EVM_TRANSACTION.

Inputs

FieldTypeDescription
recipientstring (address)Recipient address
amountstring (bigint)Amount in the token's smallest unit (wei for ETH)
tokenAddressstring | nullERC-20 contract — omit/null for native ETH

Outputs

FieldTypeDescription
calldatastringABI-encoded transfer calldata, or 0x for native ETH
tostringToken contract address (ERC-20) or recipient (ETH)
valuestringETH value to send (0x0 for ERC-20, amount for native)

BUILD_EVM_ERC20_APPROVE_CALLDATA

BUILD_EVM_ERC20_APPROVE_CALLDATA Workflow Component

ABI-encode an ERC-20 approve(spender, amount) call. The standard upstream step before any operation that pulls tokens via transferFrom — bridges, DEX swaps, lending deposits, vault entries.

Pass amount = 2^256 - 1 (max uint256) for an infinite approval.

Inputs

FieldTypeDescription
tokenAddressstring (address)ERC-20 contract to approve against
spenderstring (address)Address allowed to pull tokens (e.g. a bridge router, a Uniswap router, a vault)
amountstring (bigint)Allowance in the token's smallest unit

Outputs

FieldTypeDescription
calldatastringABI-encoded approve(spender, amount) calldata
tostringThe ERC-20 contract address (forwarded from input)
valuestringAlways "0x0"approve is a non-payable call

The output plugs directly into BUILD_EVM_TRANSACTION.

SDK example

import { WorkspaceClient, ComponentModule } from '@zafeguard/caller-sdk';
const workspace = new WorkspaceClient({ apiKey: process.env.ZAFEGUARD_API_KEY! });

const approve = await workspace.call(ComponentModule.BUILD_EVM_ERC20_APPROVE_CALLDATA, {
  tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
  spender:      '0xc026395860Db2d07ee33e05fE50ed7bD583189C7', // bridge router
  amount:       '1000000', // 1 USDC (6 decimals)
}).promise();

// Feed into BUILD_EVM_TRANSACTION → SIGN → BROADCAST → WAIT

BUILD_EVM_TRANSACTION

BUILD_EVM_TRANSACTION Workflow Component

Construct a complete unsigned EVM transaction object. Estimates gas automatically.

Config

FieldTypeDefaultDescription
type'LEGACY' | 'EIP1559''EIP1559'Transaction type. Use LEGACY for chains that don't support EIP-1559
deductFeebooleanfalseSubtract estimated gas fee from value. Useful when sending the full native balance

Inputs

FieldTypeRequiredDescription
jsonRpcUrlstringYesJSON-RPC endpoint
fromstringYesSender address
tostringYesRecipient or contract address
valuestringNoNative token amount to send in wei (bigint string, default "0")
calldatastringNoABI-encoded calldata (0x...). Omit for plain transfers
gasLimitstringNoManual gas limit override (bigint string). Auto-estimated if omitted

Outputs

FieldTypeDescription
unsignedTransactionstringRLP-encoded unsigned transaction hex
serializedHashstringTransaction hash pre-image — pass directly to SIGN_WITH_KEY_SHARE
estimatedFeestring (bigint)Estimated maximum gas fee in wei. For LEGACY: gasLimit × gasPrice. For EIP1559: gasLimit × maxFeePerGas. gasLimit includes a 20% safety buffer

SIGN_EVM_TRANSACTION

SIGN_EVM_TRANSACTION Workflow Component

Combine an unsigned transaction with an MPC signature to produce a signed transaction ready for broadcast.

Config

None.

Inputs

FieldTypeDescription
unsignedTransactionstringOutput of BUILD_EVM_TRANSACTION
signaturestringECDSA signature from SIGN_WITH_KEY_SHARE

Outputs

FieldTypeDescription
signedTransactionstringRLP-encoded signed transaction hex

BROADCAST_EVM_TRANSACTION

BROADCAST_EVM_TRANSACTION Workflow Component

Submit a signed transaction to the network and return the transaction hash.

Config

None.

Inputs

FieldTypeDescription
jsonRpcUrlstringJSON-RPC endpoint
signedTransactionstringOutput of SIGN_EVM_TRANSACTION

Outputs

FieldTypeDescription
transactionHashstringTransaction hash (0x...)

WAIT_FOR_EVM_TRANSACTION

WAIT_FOR_EVM_TRANSACTION Workflow Component

Block execution until a transaction is confirmed on-chain. Useful for sequencing dependent transactions.

Config

FieldTypeDefaultDescription
confirmationsnumber1Number of block confirmations to wait for before resolving (1–25)

Inputs

FieldTypeDescription
jsonRpcUrlstringJSON-RPC endpoint
transactionHashstringTransaction hash to monitor (0x..., 32 bytes)

Outputs

FieldTypeDescription
blockNonumberBlock number in which the transaction was included
gasUsednumberActual gas consumed by the transaction
gasPricestringEffective gas price in wei (bigint string)
gasFeestringTotal gas fee paid in wei — gasUsed × gasPrice (bigint string)

WAIT_FOR_EVM_TRANSACTION is billed PER_EXECUTION_TIME — confirmations on congested chains can take minutes. Consider your credit budget.


Full transaction workflow

import { WorkspaceClient, ComponentModule } from '@zafeguard/caller-sdk';
const workspace = new WorkspaceClient({ apiKey: process.env.ZAFEGUARD_API_KEY! });

const path = await workspace.call(ComponentModule.GET_EVM_DERIVATION_PATH, { addressIndex: 0 }).promise();
const pubKey = await workspace.call(ComponentModule.COMPUTE_PUBLIC_KEY, {
  keyId: 'my-key-id',
  derivationPath: path.derivationPath,
}).promise();
const address = await workspace.call(ComponentModule.COMPUTE_EVM_ADDRESS, {
  publicKey: pubKey.publicKey,
}).promise();
const calldata = await workspace.call(ComponentModule.BUILD_EVM_CALLDATA, {
  abi: ERC20_ABI,
  args: [recipientAddress, '1000000'],
}).promise();
const unsignedTx = await workspace.call(ComponentModule.BUILD_EVM_TRANSACTION, {
  jsonRpcUrl: RPC_URL,
  from: address.address,
  to: TOKEN_CONTRACT,
  value: '0',
  calldata: calldata.calldata,
}).promise();
// ... sign and broadcast

On this page