Smart contracts for Celer AgentPay — a generalized state-channel payment network that enables real-time, trust-free micropayments between AI agents, decentralized services, and human users.
This repo contains the on-chain L1 contract suite. Almost all activity happens off-chain via co-signed simplex states; the chain is touched only for deposits, withdrawals, settlement, and dispute resolution. For the full architecture — design principles, data structures, off-chain protocols, app channels — see the canonical docs:
A condensed in-repo orientation lives at docs/architecture-summary.md.
Six top-level contracts in src/, grouped by role:
- AgentPayWallet — Multi-owner / multi-token wallet shared by the whole network; the only contract that holds funds. Operated by a
AgentPayLedger. - PayRegistry — Append-only global record of resolved conditional-payment results, indexed by
payId = keccak256(payHash, setterAddress). - VirtContractResolver — On-demand deployer for virtual (off-chain) contracts when disputes need them on-chain.
AgentPayLedger additionally depends on the chain's canonical wrapped-native (WETH-style) contract for the multi-party-funding path on native channels — wired at deploy time via the _nativeWrap constructor argument. Users still deposit and receive native; wrapped-native is internal plumbing only.
- AgentPayLedger — Channel state machine and primary user entry point; operator of
AgentPayWallet. Logic split across libraries insrc/lib/ledgerlib/. - PayResolver — On-chain resolution of conditional payments; evaluates conditions or vouched results and writes outcomes to
PayRegistry.
- RouterRegistry — Optional registry where relay-router operators advertise themselves.
For per-contract APIs, constructor args, events, and storage, see docs/contracts.md.
src/
├── AgentPayLedger.sol # channel state machine; primary entry point (versioned)
├── AgentPayLedgerMock.sol # test-only ledger variant
├── AgentPayWallet.sol # multi-owner asset custodian (permanent)
├── PayRegistry.sol # global resolved-payment registry (permanent)
├── PayResolver.sol # conditional-pay resolution (versioned)
├── RouterRegistry.sol # optional relay-router registry
├── VirtContractResolver.sol # on-demand virtual-contract deployer
├── helper/ # test fixtures (mocks + sample ERC20) — NOT production
├── interfaces/ # I*.sol — public ABI surface
└── lib/
├── data/ # auto-generated protobuf decoders + .proto sources
└── ledgerlib/ # AgentPayLedger logic split into libraries (EIP-170 size-split)
test/ # Foundry tests
├── invariants/ # property-based / fuzz invariants for AgentPayLedger
├── utils/ # shared test base + fixtures + signing utils
└── *.t.sol # per-contract unit tests
script/ # Forge deploy scripts
lib/ # git submodules: forge-std, openzeppelin
| Document | Purpose |
|---|---|
| docs/architecture-summary.md | One-page on-chain orientation; links into the full architecture docs. |
| docs/contracts.md | Per-contract API reference (constructor, functions, events, storage). |
Native (e.g. ETH) and plain ERC-20 only. Tokens whose transferFrom delivers anything other than the requested amount — fee-on-transfer, deflationary, rebasing, ERC-777 with hooks, etc. — are not supported: channel accounting credits the requested amount, so any actual-vs-requested mismatch will desync the wallet's internal balance from its real token holdings.
| Package | Version | Purpose |
|---|---|---|
| forge-std | latest | Testing & scripting |
| openzeppelin-contracts | release-v5.3 | Access control, ERC-20, ECDSA, Pausable |
Pinned via git submodules; see .gitmodules.
MIT — see LICENSE.