Skip to main content

Pay on Behalf with EIP-7702

Beta

Pay on Behalf transactions are currently in beta. APIs, contract addresses, and behavior may change before the stable release. Use on testnet only and do not rely on this feature in production.

Token Registry v5 only

Pay on Behalf is only supported for Token Registry v5 (TR v5) contracts deployed via TDocDeployer. It is not available for earlier token registry versions. See the TR v5 migration guide if you are still on an older registry.

TrustVC supports Pay on Behalf — letting a platform (issuer) cover trade document transaction costs for its users. Users can deploy token registries, mint documents, and perform all title escrow operations without holding ETH, while gas is sponsored on their behalf by a PlatformPaymaster.

Under the hood, this is implemented as a gasless transaction flow using EIP-7702 (smart account delegation) and ERC-4337 account abstraction — the "Pay on Behalf" name describes the outcome for the user (the platform pays), while "gasless" describes the underlying mechanism you'll see referenced in code and function names.

Architecture

The system is built on three smart contracts:

ContractRole
EIP7702ImplementationShared smart account logic. EOAs delegate to this once via a type-4 transaction — their bytecode becomes 0xef0100 || impl_address, giving them full smart-account capability while keeping the same address and private key.
PlatformPaymasterPer-platform ERC-4337 paymaster deployed as a minimal-proxy clone. Sponsors gas for registry deploys, mints, and title escrow operations within configured limits.
PlatformAccountFactoryDeploys PlatformPaymaster clones deterministically via CREATE2. Cheap (~55 k gas) and the clone address is predictable before deployment.

How it works

The flow splits into a one-time admin setup (done once by the platform) and the user experience (repeated for every action the user takes). The user never sees a gas prompt or needs to hold ETH.

Admin setup

User wallet experience

In text form, the same flow:

[One-time, separate step] EOA delegates to EIP7702Implementation via a type-4 transaction
- User-owned wallet: user signs the authorization off-chain, platform owner submits it
- Platform-managed wallet: platform owner both signs and submits (it holds the key)

User (EOA, no ETH, already delegated)

│ 1. Submit UserOperation via a bundler


Bundler

│ 2. Calls EntryPoint → validates against PlatformPaymaster


PlatformPaymaster

├── Path A — Title escrow / registry calls
│ Checks: caller ∈ authorizedCallers, target ∈ authorizedRegistries or authorizedTitleEscrows
│ Enforces: dailyLimit per user

└── Path B — deployRegistry / mintDocument on the paymaster itself
deployRegistry: userWhitelist[sender] > 0 (platform whitelists users)
mintDocument: caller has MINTER_ROLE on the registry

Deployed addresses

Sepolia (chainId: 11155111)

ContractAddress
EIP7702Implementation0xa46EC3920Ac5fc54F4bA33185A91ae250aDF59B8
PlatformPaymaster (implementation)0xa24695178ea881ab7d4d105106e4906a8da4752b
PlatformAccountFactory0x7e9ef6363180baa744eb32ceab367a44f52adc9f
TDocDeployer0x64bc665056DC8bE4092e569ED13a7F273Be28cD2
EntryPoint v0.80x4337084D9E255Ff0702461CF8895CE9E3b5Ff108

Polygon Amoy (chainId: 80002)

ContractAddress
EIP7702Implementation0x044de1d4515a76ed9e431e8ec89e8d600405fd86
PlatformPaymaster (implementation)0x1c4367128933E9a88de26C723F50C288fA0fFea7
PlatformAccountFactory0xfbe1d336000d567f98ac5318f7c0144501388409
TDocDeployer0xfcafea839e576967b96ad1FBFB52b5CA26cd1D25
EntryPoint v0.80x4337084D9E255Ff0702461CF8895CE9E3b5Ff108

SDK package

The @trustvc/trustvc SDK exposes all Pay on Behalf functions under the eip7702-functions namespace. Install it once:

npm install @trustvc/trustvc@beta

Import any function directly:

import {
deployTokenRegistryGasless,
mintGasless,
transferHolderGasless,
transferBeneficiaryGasless,
transferOwnersGasless,
nominateGasless,
returnToIssuerGasless,
rejectReturnedGasless,
acceptReturnedGasless,
rejectTransferHolderGasless,
rejectTransferBeneficiaryGasless,
rejectTransferOwnersGasless,
} from "@trustvc/trustvc";
Naming

These SDK functions keep the Gasless suffix (their actual exported names), even though the feature is presented to platforms and end users as Pay on Behalf. The suffix refers to the underlying mechanism; the name doesn't change based on which bundler or paymaster infrastructure you use.

Contract addresses via gaslessConstants

The SDK also exports a gaslessConstants object with all deployed contract addresses, so you don't need to hard-code them:

import { gaslessConstants } from "@trustvc/trustvc";

// Sepolia
gaslessConstants.GASLESS_EIP7702_IMPL_ADDRESS_SEPOLIA
gaslessConstants.GASLESS_PAYMASTER_IMPL_ADDRESS_SEPOLIA
gaslessConstants.GASLESS_FACTORY_ADDRESS_SEPOLIA
gaslessConstants.TDOC_DEPLOYER_ADDRESS_SEPOLIA

// Polygon Amoy
gaslessConstants.GASLESS_EIP7702_IMPL_ADDRESS_AMOY
gaslessConstants.GASLESS_PAYMASTER_IMPL_ADDRESS_AMOY
gaslessConstants.GASLESS_FACTORY_ADDRESS_AMOY
gaslessConstants.GASLESS_TDOC_DEPLOYER_ADDRESS_AMOY

// Shared (same on all supported chains)
gaslessConstants.GASLESS_ENTRY_POINT

These are as const typed 0x${string} values — pass them directly to any SDK function or viem/ethers call without casting.

ABI exports

Contract ABIs are also exported if you need to decode logs or make low-level calls:

import { eip7702Abis } from "@trustvc/trustvc";
// eip7702Abis.PlatformPaymaster, eip7702Abis.EIP7702Implementation, etc.

Prerequisites

Before calling any Pay on Behalf function you need:

  1. A PlatformPaymaster deployed for your platform — see Setup.
  2. A bundler/paymaster provider API key — see Setup for a walkthrough using Pimlico as an example.
  3. The user's EOA delegated — a separate, one-time type-4 transaction, submitted before the user's first sponsored action (not as part of it). Two ways to get there:
    • User-owned wallet: the user's wallet signs an EIP-7702 authorization off-chain, and the platform owner submits it on-chain (paying its gas) to delegate the EOA to EIP7702Implementation.
    • Platform-managed wallet: the platform owner creates the wallet on the user's behalf and, holding its key, both signs the authorization and submits the delegation itself.
  4. A built smartAccountClient — the permissionless SmartAccountClient wrapping the delegated EOA.

All four are covered in Setup. Once set up, jump to Operations for code examples. If you're looking for how this is exposed on the TT Verify page, see Pay on Behalf on TT-web.

Disclaimer

Pay on Behalf is one possible way to sponsor a user's transaction costs. This reference implementation uses EIP-7702 smart account delegation together with Pimlico as an example bundler and paymaster infrastructure provider. Pimlico is referenced here only because it's what this implementation is built and tested against — TrustVC does not require, endorse, or favor Pimlico over any other provider. Any ERC-4337-compatible bundler and paymaster infrastructure that supports EIP-7702 can be substituted.