Abstract
This ERC defines a minimal interface (IERC8232) that allows an on-chain agent (identified via ERC-8004) to act as a programmable agency or delegated representative for a verified human owner when interacting with tokenized regulated Real World Assets (RWAs).
It provides scoped, revocable, time-bounded permissions for active operations (transfer, voting, rebalancing, yield strategies, etc.) while preserving legal beneficial ownership signals and feeding audit/reputation events back into the agentic stack.
It is designed as a higher-layer execution companion to the Regulated Agent Mandate Standard (RAMS) proposal (compliance mandates + dual canTransact checks) and works with both ERC-7943 (uRWA) and ERC-3643 (T-REX) tokens.
Motivation
The emergence of autonomous agents (ERC-8004) and regulated tokenized assets (ERC-3643, ERC-7943) creates a new primitive need: how do agents act as true on-chain representatives for verified owners when managing legal RWAs?
While the RAMS proposal elegantly solves compliance delegation (ensuring agents don't bypass KYC/AML during transfers), many agentic RWA use-cases require the agent to actively manage represented assets:
- Autonomous treasury rebalancing across tokenized bonds
- Voting on governance proposals for represented equity tokens
- Executing compliant yield strategies on permissioned DeFi pools
- Triggering forced transfers or freezes via ERC-3643 Agent roles under owner delegation
This standard adds the missing liability and execution primitive for autonomous A2A commerce involving represented RWAs. It enables:
- Clear ownership linking: Human owner (ONCHAINID) → Agent (ERC-8004 NFT) → Represented RWA positions
- Scoped delegation: Bitmask permissions + expiration for least-privilege agency
- Audit + reputation: Every action emits events for compliance trails and ERC-8004 reputation feeds
- Composability: Hooks into ERC-8183 Jobs for job-based agentic workflows
Specification
Overview
The core interface defines three phases:
- Authorization: Owner grants scoped permissions to an agent for a specific RWA token
- Validation: Any party can check if an agent is currently authorized for an action
- Execution: Agent performs a compliant action on behalf of the owner, with built-in audit logging
Vyper 0.4+ Interface & Integrations
# pragma version 0.4.0
"""
@title ERC-8232: On-Chain Agency for Represented RWAs
@author @secondfrontman
@notice Execution-oriented agency interface complementing RAMS (compliance delegation)
and ERC-8183 (agentic commerce) for active management of represented RWAs
@dev Composable with ERC-8004 (agent identity), ERC-8183 (jobs), ERC-3643/7943 (RWA compliance)
"""
interface IERC8232:
# =============================================================
# Events
# =============================================================
event AgencyAuthorized:
owner: indexed(address)
agent: indexed(address)
rwa_token: indexed(address)
permissions: uint256 # bitmask for allowed actions
expiration: uint256 # 0 = indefinite
event AgencyRevoked:
owner: indexed(address)
agent: indexed(address)
rwa_token: indexed(address)
event AgencyActionPerformed:
owner: indexed(address)
agent: indexed(address)
rwa_token: indexed(address)
action_type: uint256
payload: Bytes[1024] # optional calldata / reason hash
success: bool
# =============================================================
# View functions
# =============================================================
def isValidAgency(owner: address, agent: address, rwa_token: address) -> bool:
"""
@notice Check if agent is currently authorized to represent owner for this RWA
@dev Should verify: (1) owner has valid ONCHAINID claims if integrated,
(2) mandate not expired, (3) not revoked
"""
...
def getAgencyPermissions(owner: address, agent: address, rwa_token: address) -> uint256:
"""
@notice Return current permission bitmask for this owner-agent-RWA triplet
"""
...
def getAgencyExpiration(owner: address, agent: address, rwa_token: address) -> uint256:
"""
@notice Return expiration timestamp for this delegation (0 = indefinite)
"""
...
def getRepresentedOwner(agent: address, rwa_token: address) -> address:
"""
@notice Convenience: return owner this agent represents for given RWA (or zero)
"""
...
# =============================================================
# State-changing functions (called by owner or via ERC-1271 signature)
# =============================================================
def authorizeAgency(
agent: address,
rwa_token: address,
permissions: uint256,
expiration: uint256
) -> bool:
"""
@notice Owner authorizes agent (ERC-8004 identity) to act on their behalf for RWA
@dev Recommend supporting ERC-1271 signatures for cold wallet approval
@param permissions Bitmask of allowed actions (see constants below)
@param expiration Unix timestamp; 0 = indefinite delegation
"""
...
def revokeAgency(agent: address, rwa_token: address) -> bool:
"""
@notice Revoke all permissions for this agent on this RWA (instant, owner-only)
"""
...
# =============================================================
# Action execution (called by the agent)
# =============================================================
def performAgencyAction(
rwa_token: address,
action_type: uint256,
call: Bytes[1024]
) -> Bytes[1024]:
"""
@notice Agent executes a compliant action on behalf of represented owner
@dev Internal checks:
1. isValidAgency(owner, msg.sender, rwa_token)
2. action_type permitted in bitmask
3. Optional: RAMS mandate validity + ERC-7943/3643 canTransact
4. Execute calldata against rwa_token (via delegatecall or interface)
5. Emit AgencyActionPerformed for audit + ERC-8004 reputation feed
@return result Bytes from the executed call (or empty if void)
"""
...
# =============================================================
# Permission bitmask constants (suggested, can be extended)
# =============================================================
TRANSFER: constant(uint256) = 1 << 0 # Execute token transfers
VOTE: constant(uint256) = 1 << 1 # Cast governance votes
REBALANCE: constant(uint256) = 1 << 2 # Rebalance positions across pools
MINT_BURN: constant(uint256) = 1 << 3 # If issuer allows via Agent role
FREEZE: constant(uint256) = 1 << 4 # Trigger compliance freezes (ERC-3643)
YIELD_STRATEGY: constant(uint256) = 1 << 5 # Execute yield-optimizing actionsWith RAMS (Regulated Agent Mandate Standard)
- Use RAMS mandates to confirm that the represented owner and agent are authorized.
- Combine
isValidAgencywith underlying tokencanTransactchecks for compliance. - Ensure the agent cannot bypass KYC/AML obligations when executing on behalf of the owner.
With ERC-8183 (Agentic Commerce)
- Use
IERC8232as the execution layer for job-based workflows. - Jobs can authorize agents for scoped actions and record audit traces.
performAgencyActioncan be invoked by ERC-8183 job executors once the agent is validated.
With ERC-3643 (T-REX) Agent Role
- Map ERC-3643 agent roles to
IERC8232delegation permissions. - Use
authorizeAgencyandrevokeAgencyto manage on-chain authority for compliance-sensitive tokens. - Keep the underlying token's compliance checks intact while allowing controlled agent actions.
Rationale
- Minimal surface area: Like ERC-8183, keeps the interface small for gas efficiency and composability.
- Bitmask permissions: Easy to extend without new functions; supports least-privilege delegation.
- Expiration + revocation: Critical for security — owners can limit exposure to time-bound or instantly revocable agency.
- Audit-first design: Every action emits
AgencyActionPerformedfor compliance trails, dispute resolution, and ERC-8004 reputation feeds. - Composable, not prescriptive: Works with RAMS for compliance checks, ERC-8183 for job workflows, and either ERC-3643 or ERC-7943 for the underlying RWA token.
Backwards Compatibility
This ERC introduces a new interface with no impact on existing standards. It is designed to be opt-in: RWA tokens, agents, and owners choose to integrate based on use-case.
Security Considerations
- Authorization signatures:
authorizeAgencyshould support ERC-1271 signatures so owners can approve from cold wallets or multisigs without exposing private keys to agent contracts. - Compliance never bypassed: Agents must not circumvent the principal's ONCHAINID eligibility. When integrated with RAMS or ERC-3643, the underlying token's
canTransact/ identity checks must still pass. - Financial caps: Implementers may add optional
maxValueordailyLimitparameters toauthorizeAgencyto reduce blast radius of compromised agents. - Reentrancy:
performAgencyActionshould follow checks-effects-interactions pattern; consider using Vyper's@nonreentrantdecorator if calling external contracts. - Key rotation: Owners should be able to rotate agent addresses without revoking all delegations — consider an
updateAgentAddress(oldAgent, newAgent)extension if needed.
Copyright
Copyright and related rights waived via CC0.
