Abstract
This ERC defines a standard interface for authorizing autonomous agents (bots, AI systems, or automated accounts) to perform specific on-chain actions on behalf of users (principals). The standard provides:
- Time-bound authorizations: Optional start and end timestamps
- Usage-limited authorizations: Maximum call count with automatic revocation
- Function-level granularity: Permissions scoped to specific function selectors
- Cryptographic consent: Agents must sign consent to being authorized (EIP-712)
- Single-principal constraint: Each agent serves only one principal at a time per contract
Motivation
On-chain users and applications increasingly rely on delegated automation: trading bots, protocol keepers, relayers, schedulers, and other automated services. More recently, AI-driven assistants are emerging as another class of "agent", but the authorization problem is the same regardless of how an agent is implemented. A contract cannot (and need not) distinguish between an AI system and a traditional program; it only interacts with an account that submits transactions and signatures.
A standardized interface for agent authorization is needed to:
- Enable agents to act on-chain: Any autonomous program (bot, service, script, or AI system) needs a predictable, secure way to execute transactions on behalf of a principal without taking custody of the principal's keys.
- Provide fine-grained, bounded permissions: Principals should be able to limit what actions agents can take, for how long, and how many times, with clear revocation semantics.
- Improve safety via mutual consent: Agents must explicitly consent to being authorized, preventing accidental or malicious binding of unwilling addresses.
- Support composability: A standard interface enables cross-contract and cross-application authorization and makes it possible for wallets and tooling to present permissions consistently.
Existing delegation mechanisms (like token approvals) are either too broad (unlimited approvals) or too narrow (single-use signatures). This standard provides a balanced approach suitable for any autonomous agent scenario, with AI agents representing a prominent and growing use case rather than the only one.
Real-World Use Cases
Automated Trading Agents: Users authorize trading bots (rule-based or AI-driven) to execute trades within specific parameters (e.g., only swap functions, maximum 100 calls per day, valid for 30 days).
Gaming NPCs: Game contracts allow automated characters (scripted or AI-driven) to perform in-game actions on behalf of players during offline periods, with automatic expiration.
DeFi Position Management: Users authorize automation services to rebalance portfolios, compound yields, or manage liquidation protection with usage-limited authorizations.
DAO Proposal Execution: Governance automation can be authorized to execute approved proposals within time windows, with automatic revocation after execution.
Subscription Services: Service providers authorize payment agents to collect recurring fees with monthly call limits and renewal requirements.
Cross-Chain Relayers: Bridge/relayer agents receive time-limited authorization to relay messages, with automatic expiration preventing stale authorizations.
Production Validation
This standard has been validated through extensive production deployment and peer-reviewed academic research. In a fully on-chain gaming application deployed on opBNB (BNB Chain's Optimistic Rollup), the protocol:
- Supported 1,067,998 unique wallets over 222 active days
- Processed 5,704,860 transactions without custody violations
- Achieved peak usage of 12,791 daily active users
- Maintained complete audit trails with zero operational interruptions
- Demonstrated immediate revocation effectiveness in practice
This production deployment validates the security properties and practical viability of the delegation model at scale.
The formal capability semantics, security invariants, and production results are documented in a peer-reviewed industrial poster.1
Comparison with Existing Standards
This ERC occupies a unique position relative to existing delegation standards:
| Feature | ERC-4337 | EIP-7702 | This ERC |
|---|---|---|---|
| Address Type | Smart wallet | EOA | EOA |
| Custody | Smart wallet | EOA | EOA preserved |
| Granularity | Session keys | Tx-scoped | Function-level |
| Limits | Time-based | Per-tx | Usage- and time-bounded |
| Revocation | Wallet-specific | Tx ends | Immediate |
| Chains | EVM only | Ethereum | Multi-chain |
| Migration | Required | None | None |
Key Differentiators:
- Unlike smart account wallets (ERC-4337) that relocate custody to contract accounts, this ERC preserves EOA custody without migration
- Unlike single-use EOA code delegation (EIP-7702), this ERC introduces persistent, function-level capabilities
- This ERC remains compatible with account abstraction features such as bundlers and paymasters, preserving existing wallet infrastructure while enabling fine-grained delegation
ERC-2612 (Permit)
- ERC-2612 provides gasless token approvals via signatures
- This ERC generalizes the signature-based authorization pattern beyond token transfers
- Both use EIP-712 typed data and nonces for replay protection
- This ERC adds time bounds, usage limits, and function-level granularity
ERC-4337 (Account Abstraction)
- ERC-4337 abstracts account logic for flexible transaction validation
- This ERC focuses on agent-level delegation within existing accounts
- ERC-4337 UserOperations require bundlers; this ERC works with standard transactions
- Complementary: smart accounts can implement this interface for agent delegation
ERC-6900 (Modular Accounts)
- ERC-6900 defines plugin architecture for modular smart accounts
- This ERC can be implemented as an ERC-6900 execution plugin
- ERC-6900 focuses on account modularity; this ERC focuses on agent authorization semantics
- Both support EIP-165 interface detection for composability
ERC-7579 (Minimal Modular Accounts)
- ERC-7579 provides minimal modular account interface
- Similar complementary relationship as with ERC-6900
- This ERC's authorization module could be added to ERC-7579 accounts
Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Definitions
- Principal: The account (EOA or contract) delegating authority
- Agent: The account receiving authorization to act on behalf of the principal
- Selector: A 4-byte function selector identifying the authorized function
- Authorization: A tuple of (principal, agent, selector, startTime, endTime, allowedCalls)
Interface
Contracts implementing this standard MUST implement IERC8118AgentAuthorizationBase:
interface IERC8118AgentAuthorizationBase {
// Events
event AgentAuthorized(
address indexed principal,
address indexed agent,
bytes4 indexed selector,
uint256 startTime,
uint256 endTime,
uint256 allowedCalls
);
event AgentRevoked(
address indexed principal,
address indexed agent,
bytes4 indexed selector
);
// Errors
error InvalidAgentAddress();
error InvalidSelector();
error ZeroCallsNotAllowed();
error ValueExceedsBounds();
error SignatureExpired();
error InvalidSignature();
error AgentAlreadyBound();
error NoAuthorizationExists();
error NotAuthorized();
// Write Functions
function authorizeAgent(
address agent,
bytes4 selector,
uint256 startTime,
uint256 endTime,
uint256 allowedCalls,
uint256 deadline,
bytes calldata signature
) external;
function batchAuthorizeAgent(BatchAuthorization[] calldata batch) external;
function revokeAgent(address agent, bytes4 selector) external;
function batchRevokeAgent(address agent, bytes4[] calldata selectors) external;
// View Functions
function isAuthorizedAgent(
address principal,
address agent,
bytes4 selector
) external view returns (bool);
function getAgentAuthorization(
address principal,
address agent,
bytes4 selector
) external view returns (uint256 startTime, uint256 endTime, uint256 remainingCalls);
function principalOf(address agent) external view returns (address);
function nonces(address agent) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
struct BatchAuthorization {
address agent;
bytes4 selector;
uint256 startTime;
uint256 endTime;
uint256 allowedCalls;
uint256 deadline;
bytes signature;
}Optional Update Extension
Contracts MAY implement IERC8118AgentAuthorizationUpdatable for in-place authorization updates:
interface IERC8118AgentAuthorizationUpdatable is IERC8118AgentAuthorizationBase {
event AgentAuthorizationUpdated(
address indexed principal,
address indexed agent,
bytes4 indexed selector,
uint256 newStartTime,
uint256 newEndTime,
uint256 newAllowedCalls
);
function updateAgentAuthorization(
address agent,
bytes4 selector,
uint256 newStartTime,
uint256 newEndTime,
uint256 newAllowedCalls,
uint256 deadline,
bytes calldata signature
) external;
}Update Extension Behavior
The updateAgentAuthorization function allows principals to modify existing authorizations:
-
The function MUST revert with
NoAuthorizationExistsif no authorization exists for the specified principal-agent-selector tuple. -
Updates are classified as either restrictions or escalations:
- Restriction (no signature required): reducing
remainingCalls, narrowing the time window - Escalation (signature required): increasing
remainingCalls, extending the time window
Sentinel Value Semantics for Comparisons:
Since
startTime = 0means "immediately valid" andendTime = 0means "no expiration" (infinite), comparisons MUST treat these sentinel values as follows:For
startTime(where 0 = immediate, lower is more permissive):0 → non-zero: RESTRICTION (adding a start delay)non-zero → 0: ESCALATION (removing start delay)non-zero → higher non-zero: RESTRICTION (increasing delay)non-zero → lower non-zero: ESCALATION (decreasing delay)
For
endTime(where 0 = infinite/no expiry, higher is more permissive):0 → non-zero: RESTRICTION (adding an expiration)non-zero → 0: ESCALATION (removing expiration, granting infinite validity)non-zero → lower non-zero: RESTRICTION (earlier expiration)non-zero → higher non-zero: ESCALATION (later expiration)
For
remainingCalls:current → lower: RESTRICTIONcurrent → higher: ESCALATION
- Restriction (no signature required): reducing
-
For escalations, the function MUST:
- Validate the agent's EIP-712 signature (same
AgentConsentstructure asauthorizeAgent) - Revert with
SignatureExpiredifblock.timestamp > deadline - Revert with
InvalidSignatureif the signature is invalid - Increment the agent's nonce after successful update
- Validate the agent's EIP-712 signature (same
-
The function MUST:
- Revert with
ZeroCallsNotAllowedifnewAllowedCallsis 0 (userevokeAgentinstead) - Revert with
ValueExceedsBoundsif values exceed storage bounds - Emit
AgentAuthorizationUpdatedon success
- Revert with
Behavior Specification
Authorization
The principal for all authorization operations MUST be msg.sender. The caller of authorizeAgent is always the principal granting the authorization.
-
The
authorizeAgentfunction MUST:- Set the principal to
msg.sender(the caller is the principal) - Revert with
InvalidAgentAddressifagentis the zero address - Revert with
InvalidSelectorifselectoris0x00000000 - Revert with
ZeroCallsNotAllowedifallowedCallsis 0 - Revert with
ValueExceedsBoundsifstartTimeorendTimeexceedstype(uint48).max, orallowedCallsexceedstype(uint64).max - Revert with
SignatureExpiredifblock.timestamp > deadline - Revert with
InvalidSignatureif the signature is invalid or theprincipalfield in the signed message does not matchmsg.sender - Revert with
AgentAlreadyBoundif the agent is bound to a different principal - Increment the agent's nonce after successful authorization
- Emit
AgentAuthorizedon success
If an authorization already exists for the
(msg.sender, agent, selector)tuple,authorizeAgentMUST overwrite the existing authorization with the new parameters. This behavior mirrors ERC-20approvesemantics where a new approval replaces the previous one. Principals who wish to extend an existing authorization without replacement SHOULD use the optionalupdateAgentAuthorizationfunction if available. - Set the principal to
-
The signature MUST be an EIP-712 typed data signature with the following structure:
AgentConsent( address principal, address agent, bytes4 selector, uint256 startTime, uint256 endTime, uint256 allowedCalls, uint256 nonce, uint256 deadline ) -
For contract agents, the signature MUST be validated using EIP-1271
isValidSignature. -
The EIP-712 domain MUST use the following structure:
EIP712Domain( string name, string version, uint256 chainId, address verifyingContract )Implementations SHOULD use
name = "Agent Authorization"andversion = "1"for interoperability, but MAY use contract-specific values. ThechainIdMUST be the current chain ID, andverifyingContractMUST be the contract address implementing this interface.
Time and Usage Bounds
Time bounds use sentinel values for unbounded conditions:
- A
startTimeof 0 means the authorization is immediately valid (no start restriction) - An
endTimeof 0 means the authorization has no expiration (no end restriction)
Authorization time validity MUST be evaluated as:
- If
startTime != 0ANDblock.timestamp < startTime, authorization is NOT valid - If
endTime != 0ANDblock.timestamp > endTime, authorization is NOT valid - Otherwise, the authorization is time-valid
Note: If startTime > endTime (where both are non-zero), the authorization will never be time-valid. Implementations MAY reject such authorizations at creation time.
Usage limits:
- Each successful call through a protected function MUST decrement
remainingCalls(the current remaining count) - When
remainingCallsreaches 0, the authorization MUST be automatically revoked - The
allowedCallsparameter inauthorizeAgentsets the initial value ofremainingCalls
Single-Principal Constraint
Each agent can only be bound to one principal at a time within a contract instance. This prevents conflicting instructions from multiple principals.
Revocation
- Principals can revoke authorizations at any time using
revokeAgent - The
revokeAgentfunction MUST revert withNoAuthorizationExistsif the specified authorization does not exist - When an agent's last authorization is revoked, the agent becomes unbound (can be authorized by a different principal)
View Functions
View functions MUST NOT revert for valid inputs and MUST return predictable values:
-
isAuthorizedAgent(principal, agent, selector)MUST returntrueif and only if:- An authorization exists for the
(principal, agent, selector)tuple, AND - The authorization is time-valid per the rules in "Time and Usage Bounds", AND
remainingCalls > 0
Otherwise, it MUST return
false. This function MUST NOT revert. - An authorization exists for the
-
getAgentAuthorization(principal, agent, selector)MUST:- Return
(startTime, endTime, remainingCalls)from storage if an authorization exists - Return
(0, 0, 0)if no authorization exists for the tuple - This function MUST NOT revert for valid addresses and selectors
- Return
-
principalOf(agent)MUST:- Return the address of the principal the agent is currently bound to
- Return
address(0)if the agent is not bound to any principal - This function MUST NOT revert
-
nonces(agent)MUST:- Return the current nonce for the agent (used for signature replay protection)
- Return
0for agents that have never been authorized - This function MUST NOT revert
Batch Operations
Batch operations provide gas-efficient multi-authorization management:
-
batchAuthorizeAgentMUST:- Process each
BatchAuthorizationin array order (index 0 first) - Be atomic: if any single authorization fails, the entire batch MUST revert
- The principal for all authorizations in the batch MUST be
msg.sender - Each element's signature MUST use the same
AgentConsentEIP-712 typed data structure asauthorizeAgent
Nonce Sequencing for Batch Operations:
When the same agent appears multiple times in a batch (with different selectors), signatures MUST use sequential nonces:
- The first authorization for an agent uses
nonces(agent)(the current stored nonce) - Each subsequent authorization for the same agent in the batch uses
nonces(agent) + N, where N is the number of prior authorizations for that agent in the batch - The agent's stored nonce is incremented once per successful authorization
Example: If agent A has nonce=5 and appears at batch indices 0, 2, and 4:
- Index 0: signature uses nonce 5
- Index 2: signature uses nonce 6
- Index 4: signature uses nonce 7
- After batch completes: stored nonce becomes 8
- Process each
-
batchRevokeAgentMUST:- Revoke all specified selectors for the given agent
- Be atomic: if any revocation fails (e.g., authorization doesn't exist), the entire batch MUST revert
EIP-165 Interface Detection
Contracts MUST implement EIP-165 and return true for:
IERC8118AgentAuthorizationBaseinterface ID:0x9e22ca0fIERC8118AgentAuthorizationUpdatableinterface ID (if implemented):0x51c6e02e
The base interface ID is calculated as the XOR of all function selectors:
authorizeAgent(address,bytes4,uint256,uint256,uint256,uint256,bytes) = 0xcc14c2e4
batchAuthorizeAgent((address,bytes4,uint256,uint256,uint256,uint256,bytes)[]) = 0xdbfb37e9
revokeAgent(address,bytes4) = 0xe9bbcb43
batchRevokeAgent(address,bytes4[]) = 0x46c0b6de
isAuthorizedAgent(address,address,bytes4) = 0x616c0c47
getAgentAuthorization(address,address,bytes4) = 0x6eb21fd1
principalOf(address) = 0x61e20a1c
nonces(address) = 0x7ecebe00
DOMAIN_SEPARATOR() = 0x3644e515The updatable extension ID is: 0x9e22ca0f XOR updateAgentAuthorization selector (0xcfe42a21) = 0x51c6e02e
Rationale
Agent Consent Requirement
Requiring agents to sign consent prevents principals from binding agents without their knowledge. This is crucial for:
- Preventing DOS attacks where malicious principals could bind agents to unusable contracts
- Ensuring agents are aware of their responsibilities
- Providing a clear audit trail of consent
Single-Principal Constraint
While limiting, this constraint:
- Prevents conflicting instructions from multiple principals
- Simplifies the security model
- Reduces gas costs (no need to track multiple principals per agent)
Null Selector Prohibition
The zero selector (0x00000000) is prohibited to prevent ambiguity with wildcard authorizations, which are explicitly not supported for security reasons.
Packed Storage
Authorization data uses packed storage (uint48 for timestamps, uint64 for call count) to:
- Reduce gas costs for storage operations
- Keep authorization data in a single storage slot
- Maintain practical limits (timestamps valid for ~8.9 million years, call counts up to ~18 quintillion)
Backwards Compatibility
This ERC introduces a new interface and does not modify existing standards. Contracts implementing this standard can coexist with other delegation mechanisms.
Account Abstraction Compatibility
This ERC is designed to complement rather than replace account abstraction infrastructure:
- Bundler Integration: Authorized agent transactions can be bundled via ERC-4337 bundlers
- Paymaster Support: Gas sponsorship via paymasters is fully compatible with agent-authorized calls
- No Wallet Migration: Existing EOA wallets can use this standard without migration to smart contract wallets
- Minimal Integration Path: dApps can add capability-based delegation by implementing policy guards on existing contracts
Integration Strategies
Existing Contracts: Contracts without this interface can be wrapped by a proxy implementing IERC8118AgentAuthorizationBase that delegates authorized calls to the underlying contract.
Token Approvals: This standard operates independently of ERC-20/ERC-721/ERC-1155 approval mechanisms. An agent authorized via this interface still requires appropriate token approvals for transfers.
Access Control: This standard complements but does not replace role-based access control (e.g., OpenZeppelin AccessControl). Contract owners should consider whether agent authorizations should be granted in addition to or instead of role assignments.
Upgrade Considerations
Contracts using the optional update extension (IERC8118AgentAuthorizationUpdatable) should ensure upgrade mechanisms preserve authorization state. When using proxy patterns (ERC-1967, UUPS), the authorization storage slots must remain consistent across implementations.
Test Cases
The reference implementation includes a comprehensive test suite with 98 tests covering:
Authorization Tests
- Valid authorization with proper EIP-712 signature
- Rejection of zero agent address (
InvalidAgentAddress) - Rejection of zero selector (
InvalidSelector) - Rejection of zero allowed calls (
ZeroCallsNotAllowed) - Rejection of expired signatures (
SignatureExpired) - Rejection of invalid signatures (
InvalidSignature) - Rejection when agent is bound to different principal (
AgentAlreadyBound) - Rejection of values exceeding storage bounds (
ValueExceedsBounds)
Execution Tests
- Successful execution with valid authorization
- Proper decrementing of
allowedCallscounter - Automatic revocation when
allowedCallsreaches zero - Time-bound enforcement (before
startTime, afterendTime) - Principal context preservation during callbacks
Revocation Tests
- Manual revocation by principal
- Agent unbinding after last authorization revoked
- Rejection of non-existent authorization revocation (
NoAuthorizationExists)
Batch Operation Tests
- Batch authorization with multiple agent-selector pairs
- Atomic failure on any invalid authorization in batch
- Batch revocation of multiple selectors
Contract Agent Tests (EIP-1271)
- Authorization of smart contract agents
- Signature validation via
isValidSignature
Update Extension Tests
- Restriction without signature (reducing calls, narrowing time window)
- Escalation requiring signature (increasing calls, extending time window)
- Rejection of non-existent authorization update
Reference Implementation
A reference implementation is available in the assets folder:
AgentAuthorizationBase.sol: Base implementation with EIP-712 signatures and single-principal constraintAgentAuthorizationUpdatable.sol: Extended implementation with in-place authorization updatesIERC8118AgentAuthorizationBase.sol: Base interface definitionIERC8118AgentAuthorizationUpdatable.sol: Updatable extension interfaceAuthorizationTypes.sol: Shared struct definitionsAuthorizationErrors.sol: Custom error definitions
Security Considerations
Formal Security Properties
This standard provides four formal security guarantees, validated through production deployment:
-
Custody Preservation: Agents invoke only those methods that a user-signed capability authorizes, scoped to the chain, the contract, and the selector set. The principal's private key is never shared with the agent.
-
Bounded Authority: On-chain verification of quota, scope, and expiry occurs before execution. Any successful call consumes exactly one unit of allowance, ensuring agents cannot exceed their authorization.
-
Cryptographic Attribution: Every delegated action is linked to its capability identifier and the corresponding user signature, providing complete audit trails.
-
Effective Revocation: Once a revocation is finalized on-chain, any subsequent use fails immediately. Production deployment demonstrated immediate revocation effectiveness across millions of transactions.
Signature Replay Protection
- Nonces prevent replay of the same signature
- Deadlines limit the validity window of signatures
- EIP-712 domain separator prevents cross-contract replay
- Chain ID in domain separator prevents cross-chain replay
Reentrancy
Protected functions should follow the checks-effects-interactions pattern. The modifier validates and consumes authorization before executing the protected function.
Front-Running
- Revocation transactions may be front-run by agents attempting to use remaining calls
- Consider using private mempools for sensitive revocations
- Time-based restrictions (endTime) provide additional protection
Agent Key Security
Compromised agent keys can be mitigated by:
- Setting conservative
allowedCallslimits - Using short time windows
- Prompt revocation via
revokeAgent
Copyright
Copyright and related rights waived via CC0.
Footnotes
-
↩
{ "type": "paper-conference", "id": "brains2025", "author": [ { "family": "Sun", "given": "Alvin" }, { "family": "Zhang", "given": "Tim" }, { "family": "Wu", "given": "Xiao" }, { "family": "Cai", "given": "Wei" } ], "DOI": "10.1109/BRAINS67003.2025.11302911", "title": "Custody-Preserving AI Agent Delegation for Decentralized Applications via World AI Protocol", "container-title": "2025 7th Conference on Blockchain Research & Applications for Innovative Networks and Services (BRAINS)", "publisher": "IEEE", "event-place": "Zurich, Switzerland", "original-date": { "date-parts": [ [2025] ] }, "URL": "https://ieeexplore.ieee.org/document/11302911" }
