Cortex

Contracts Reference

Cortex combines identity, policy, intents, participant registries, and commerce primitives into an onchain protocol layer.

AgentRegistry

Stores agent identity records. Agents are registered by their owner address.

Functions

FunctionAccessDescription
registerAgent(metadataURI, pubkey, capabilitiesHash)AnyoneRegister a new agent. Returns agentId.
updateAgent(agentId, metadataURI, capabilitiesHash)OwnerUpdate agent metadata. Reverts if revoked.
revokeAgent(agentId)OwnerPermanently revoke an agent.
getAgent(agentId)ViewGet agent record. Reverts if not found.
getAgentsByOwner(owner)ViewGet all agent IDs for an owner.

Events

event AgentRegistered(uint256 indexed agentId, address indexed owner, string metadataURI);
event AgentUpdated(uint256 indexed agentId, string metadataURI, bytes32 capabilitiesHash);
event AgentRevoked(uint256 indexed agentId);

Errors

error Unauthorized();
error AgentNotFound();
error AgentAlreadyRevoked();

IntentBook

Manages the intent lifecycle: submit, fill, cancel. Uses EIP-712 signed typed data.

EIP-712 Domain

name: "AgentIntentBook"
version: "1"
chainId: <chain ID>
verifyingContract: <IntentBook address>

Intent Struct

struct Intent {
    address owner;
    IntentType intentType;
    Constraints constraints;
    address inputToken;
    address outputToken;
    uint256 nonce;
}

struct Constraints {
    uint256 amountInMax;
    uint256 amountOutMin;
    uint256 deadline;
    uint16 slippageBps;
}

Functions

FunctionAccessDescription
submitIntent(intent, v, r, s)AnyoneSubmit a signed intent. Validates signature, nonce, deadline, slippage.
cancelIntent(intentId)OwnerCancel an open intent.
fillIntent(intentId, fill)AnyoneFill an open intent. Validates constraints and expiry.
getIntent(intentId)ViewGet intent data.
getIntentStatus(intentId)ViewGet intent status (OPEN, FILLED, CANCELLED, EXPIRED).

Events

event IntentSubmitted(uint256 indexed intentId, address indexed owner, uint256 nonce);
event IntentCancelled(uint256 indexed intentId);
event IntentFilled(uint256 indexed intentId, address indexed solver, uint256 amountIn, uint256 amountOut);

Errors

error Unauthorized();
error InvalidNonce();
error IntentExpired();
error IntentNotOpen();
error ConstraintViolation();
error InvalidSlippage();     // slippageBps > 10,000
error InvalidDeadline();     // deadline <= block.timestamp
error InvalidSignature();    // recovered signer != intent.owner

PolicyModule

Enforces per-account policies: spend limits, target allowlists, function selector allowlists.

Functions

FunctionAccessDescription
setSpendLimit(token, maxPerDay)AccountSet daily spend limit. 0 removes limit.
setTargetAllowed(target, allowed)AccountAdd/remove target from allowlist.
setFunctionAllowed(target, selector, allowed)AccountAllow/disallow function selector on target.
setUseFunctionAllowlist(enabled)AccountEnable/disable function-level checks.
setSignedPaymentPolicy(...)AccountConfigure facilitator/x402-style delegated payment budgets.
recordSignedPayment(...)AccountRecord signed payment spend and payment-hash replay protection.
checkTransaction(target, value, data)ViewValidate against all policies.
recordSpend(token, amount)AccountRecord spending against daily limit.
getSpendLimit(account, token)ViewGet spend limit config.
getSpentToday(account, token)ViewAmount spent in current 24h window.
isTargetAllowed(account, target)ViewCheck if target is on allowlist.
isFunctionAllowed(account, target, selector)ViewCheck if function is allowed on target.

Events

event SpendLimitSet(address indexed account, address indexed token, uint256 maxPerDay);
event TargetAllowlistUpdated(address indexed account, address indexed target, bool allowed);
event FunctionAllowlistUpdated(address indexed account, address indexed target, bytes4 selector, bool allowed);
event SpendRecorded(address indexed account, address indexed token, uint256 amount, uint256 dailyTotal);

Errors

error Unauthorized();
error TargetNotAllowed(address target);
error FunctionNotAllowed(address target, bytes4 selector);
error DailySpendLimitExceeded(address token, uint256 attempted, uint256 remaining);
error DelegateCallNotAllowed();

Spend Limit Mechanics

  • 24-hour rolling window based on lastResetTimestamp
  • Window resets when block.timestamp >= lastResetTimestamp + 1 day
  • maxPerDay = 0 means no limit configured (allows freely)
  • Limits are per-account, per-token
  • address(0) represents native ETH
  • Wallet transfers and swaps use normal target/function policy plus spend limits
  • Facilitator-mediated and x402 payments use signed payment policies

PolicyAccount (ERC-4337)

Smart account that delegates policy validation to PolicyModule.

Functions

FunctionAccessDescription
execute(target, value, data)EntryPoint or selfExecute a call after policy check.
validateUserOp(userOp, userOpHash, missingAccountFunds)EntryPointValidate ERC-4337 UserOp signature.

The account checks PolicyModule.checkTransaction() before executing any call and records ETH spend via PolicyModule.recordSpend().


SolverRegistry and AttestorRegistry

Permissionless registries expose solver operators and attestors with metadata, capability/schema hashes, active status, and indexed performance counters.

event SolverRegistered(uint256 indexed solverId, address indexed operator, string metadataURI, bytes32 capabilitiesHash, uint256 bond);
event AttestorRegistered(uint256 indexed attestorId, address indexed operator, string metadataURI, bytes32 schemasHash);

CommerceRegistry

Registers merchants, services, payment facilitators, canonical quote commitments, receipts, fulfillment, trust signals, and disputes for agentic commerce.

Quote Commitment

struct QuoteCommitment {
    uint256 merchantId;
    uint256 serviceNumericId;
    address agent;
    address token;
    address facilitator;
    uint256 amount;
    PaymentRail paymentRail;
    uint256 expiresAt;
    uint256 paymentNonce;
    bytes32 resourceHash;
    bytes32 termsHash;
    bytes32 x402PayloadHash;
}

The quote hash binds chain ID, registry address, service terms, payment terms, and protocol fee terms. Basic transfers and swaps bind through policy and terms hashes; x402 flows additionally bind the x402 payload hash.

Events

event QuoteCommitted(bytes32 indexed quoteHash, uint256 indexed merchantId, uint256 indexed serviceNumericId, address agent, address token, address facilitator, uint256 amount, PaymentRail paymentRail, uint16 protocolFeeBps, uint256 protocolFeeAmount, uint256 expiresAt, uint256 paymentNonce, bytes32 resourceHash, bytes32 termsHash, bytes32 x402PayloadHash);
event ReceiptRecorded(uint256 indexed receiptId, bytes32 indexed quoteHash, address indexed agent, uint256 merchantId, uint256 serviceNumericId, address token, uint256 amount, PaymentRail paymentRail, uint16 protocolFeeBps, uint256 protocolFeeAmount, address facilitator, bytes32 resultHash, bytes32 resourceHash, bytes32 fulfillmentHash);
event FulfillmentRecorded(uint256 indexed receiptId, bytes32 fulfillmentHash);
event TrustSignalRecorded(uint256 indexed signalId, SignalSubject indexed subjectType, uint256 indexed subjectId, SignalKind kind, address reporter, bytes32 signalHash);
event DisputeOpened(uint256 indexed disputeId, uint256 indexed receiptId, address indexed opener, bytes32 reasonHash);
event DisputeResolved(uint256 indexed disputeId, DisputeStatus status, bytes32 resolutionHash);

PROTOCOL_FEE_BPS is currently 0. Fee fields are emitted and indexed for analytics without charging early usage.