Bridge with ERC-4337
Gasless USD₮0 bridging using WalletAccountEvmErc4337 and paymaster options.
This guide covers prerequisites, how to create an ERC-4337 account, and how to call the bridge with paymaster configuration.
Prerequisites
@tetherto/wdk-wallet-evm-erc-4337installed alongside @tetherto/wdk-protocol-bridge-usdt0-evm.- Bundler and paymaster endpoints for your chain (example uses Arbitrum public URLs from the API reference).
- An ERC-4337 source chain with a configured transaction-value helper: Ethereum, Arbitrum, Plasma, or Polygon.
Create a WalletAccountEvmErc4337 account
You can construct an ERC-4337 signing account using new WalletAccountEvmErc4337(seed, path, config) with chain, provider, bundler, and paymaster settings:
import { WalletAccountEvmErc4337 } from '@tetherto/wdk-wallet-evm-erc-4337'
const seedPhrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
const account = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
chainId: 42161,
provider: 'https://arb1.arbitrum.io/rpc',
bundlerUrl: 'https://api.candide.dev/public/v3/42161',
safeModulesVersion: '0.3.0',
paymasterUrl: 'https://api.candide.dev/public/v3/42161',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
paymasterToken: { address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9' }
})You can wrap that account with the new Usdt0ProtocolEvm(account, config?) constructor:
import Usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
const bridgeProtocol = new Usdt0ProtocolEvm(account)Run a gasless bridge with paymaster options
You can execute bridge() with a second argument that includes paymasterToken and an optional bridgeMaxFee override. Do not submit a separate account.approve() call for this flow. The protocol builds an ERC20 approval to the source-chain transaction-value helper and the helper bridge call, then submits both in one UserOperation.
const USDT_TOKEN_ADDRESS = process.env.USDT_SOURCE_TOKEN_ADDRESS
const USDT0_OFT_ADDRESS = process.env.USDT0_OFT_ADDRESS
const amount = 1000000n
const paymasterToken = { address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9' }
const result = await bridgeProtocol.bridge(
{
targetChain: 'polygon',
recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
token: USDT_TOKEN_ADDRESS,
amount,
oftContractAddress: USDT0_OFT_ADDRESS
},
{
paymasterToken
}
)
console.log('Bridge hash:', result.hash)
console.log('Account fee:', result.fee)
console.log('Bridge fee:', result.bridgeFee)The bundled approval and helper call produce one UserOperation hash. The protocol approves enough source token for the amount plus its helper-calculated bridge fee and tolerance.
In 1.0.0-beta.7, bridgeFee for this helper flow is in bridged-token base units. The account's fee is in native base units for native gas, paymaster-token base units for token-paid gas, or zero for sponsored gas. The protocol numerically adds those values when enforcing bridgeMaxFee. Do not interpret the sum as one currency or set an ERC-4337 cap until your integration has confirmed compatible units for its payment mode.
Paymaster policies, token addresses, and URLs are service-specific. Confirm supported tokens and networks with your bundler or paymaster provider before production use.
Next Steps
Bridge to non-EVM chains in Bridge cross-ecosystem. For failure modes and cleanup, read Handle errors.