# Auto Contracts > A standard for agentic contracts settled onchain. > Auto contracts let agents make binding agreements with each other onchain. > Each contract pairs a smart contract with a markdown file. A third agent — the resolver — evaluates whether the terms were met and settles the contract. Site: https://autocontracts.org GitHub: https://github.com/j-s/autocontracts --- # Auto Contract Standard: Interface ## Abstract This standard defines `IAutoContract`, a minimal Solidity interface for smart contracts whose settlement depends on a bounded subjective judgment — a decision constrained to a finite set of outcomes based on pre-agreed criteria — made by a designated resolver agent. The interface specifies a generic state machine, role-based access, and hash-anchored terms. It can be specialized for escrow, governance, disputes, milestones, bounties, insurance claims, or any other use case requiring off-chain judgment with on-chain finality. ## Motivation Existing smart contracts settle deterministic conditions well: token transfers trigger when a balance threshold is met, timelocks expire on schedule, multisig thresholds are counted. But a growing class of on-chain agreements depends on questions that have no deterministic answer: - Does a deliverable satisfy a milestone? - Is a governance proposal compliant with a DAO's charter? - Does submitted evidence substantiate an insurance claim? - Has a bounty been fulfilled to specification? These questions require bounded judgment. Today, projects handle this with ad hoc contract designs that embed use-case-specific roles (buyer/seller), outcomes (release/refund), and state machines (funded/submitted). This makes each implementation incompatible with tooling, indexers, resolvers, and frontends built for any other. This standard extracts the common structure: two parties create a contract anchored by hashed terms, one party submits evidence, a designated resolver renders a decision from a finite outcome set, and the implementation settles accordingly. By standardizing this lifecycle, any resolver agent, indexer, or interface can interact with any auto contract regardless of its domain. --- ## Specification ### Execution Flow An auto contract is executed in two onchain transactions: 1. **Both parties verify offchain.** The parties review the markdown agreement document and independently compute its hash. They agree on the resolver and terms before either party transacts. 2. **Creator proposes.** The creator calls `create()` to register the contract onchain, anchoring the `termsHash`. The contract enters `Created` state. This is a proposal, not yet binding. 3. **Counterparty accepts.** The counterparty calls `accept()` to confirm they have verified the terms and agree. The contract enters `Active` state. It is now binding — both parties have transacted onchain against the same terms hash. 4. **Evidence is submitted.** A party calls `submit()` to record a deliverable or evidence hash. The contract enters `Submitted` state. 5. **Resolver settles.** The resolver calls `resolve()` with an outcome and resolution hash. The contract enters `Resolved` state. Settlement effects execute atomically. The `contractURI()` view function returns the URI where the agreement document can be retrieved. Any party can fetch the document, hash it, and verify it matches the onchain `termsHash`. ### State Machine Every contract instance moves through these states: \`\`\`text None -> Created -> Active -> Submitted -> Resolved \\ \\ \\ +---> Cancelled +------------> Cancelled \`\`\` | State | Meaning | | ----------- | ------------------------------------------------------------------- | | `None` | Default zero value. No contract instance exists at this identifier. | | `Created` | Proposed onchain by the creator. Awaiting counterparty acceptance. | | `Active` | Counterparty has accepted. The agreement is binding. | | `Submitted` | Evidence or deliverable hash recorded. Awaiting resolver judgment. | | `Resolved` | Resolver has rendered a final decision. Terminal state. | | `Cancelled` | Contract voided before resolution. Terminal state. | Transitions cannot skip states — `Created` never jumps straight to `Resolved`. Implementations may add domain-specific sub-states, but these five core states must be present and queryable. ### Roles An auto contract instance involves exactly three roles: | Role | Description | | ---------------- | ------------------------------------------------------------------------------ | | **Creator** | The address that calls `create`. Typically the party initiating the agreement. | | **Counterparty** | The second party to the agreement, designated at creation. | | **Resolver** | The designated agent address authorized to render a decision. | Only the specified role may call its corresponding lifecycle function, and implementations must enforce this. The creator and counterparty must be distinct addresses. The resolver should be a third party — sharing an address with either is discouraged, and valid only where the domain explicitly permits it. ### Outcome The resolver's decision is a `bytes32` value rather than a domain-specific enum. The agreement format standard defines named outcome labels; each is converted to `bytes32` onchain via `keccak256(bytes(label))`. This lets any domain define its own outcome set without changing the interface. | Value | Meaning | | ------------------- | ---------------------------------------------------------------------------- | | `bytes32(0)` | No decision rendered (default). | | Any other `bytes32` | Implementation-defined outcome, derived from the agreement's outcome labels. | A resolution with outcome `bytes32(0)` must be rejected. Implementations should document their outcome mapping in a companion standard or in contract-level NatSpec. ### Hash Anchoring Three hashes anchor off-chain artifacts to on-chain state: | Hash | Anchors | Set During | | ---------------- | --------------------------------------------------------- | ---------- | | `termsHash` | The markdown agreement defining the subjective terms. | `create` | | `submissionHash` | The evidence, deliverable, or claim submitted for review. | `submit` | | `resolutionHash` | The resolver's decision document including rationale. | `resolve` | All hashes are `bytes32`. This standard doesn't mandate a hashing algorithm, though SHA-256 and Keccak-256 are recommended; companion standards (such as the agreement format) should pin down the exact algorithm and canonicalization. ### Document Storage The `contractURI` view function returns a URI pointing to the markdown agreement document. The URI provides **retrieval**; the `termsHash` provides **verification**. Any party can fetch the document from the URI, hash it, and confirm it matches the onchain `termsHash`. Implementations should store the URI onchain — passed to `create` or set separately. Common schemes are `ipfs://`, `ar://`, and `https://`. If the URI isn't stored onchain, `contractURI` may return an empty string. For private agreements (`visibility: private` in the frontmatter), the document at the URI must be access-controlled so only the parties and resolver can retrieve it. The `termsHash` stays public onchain — anyone who obtains the document another way can still verify it against the hash. The principle: **the hash is always public and verifiable; access to the document is controlled.** ### Interface Conforming implementations MUST implement this interface, defined in `IAutoContract.sol`: \`\`\`solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.26; /// @title IAutoContract /// @notice Generic state-machine interface for markdown-defined agreements. /// @dev Terms, evidence, and decisions stay offchain; the contract stores only /// hashes, parties, and state. Outcomes are bytes32 so any domain can map its /// result (release, refund, approve, reject, split) to a settlement action. interface IAutoContract { /// @notice Lifecycle states for every contract instance. enum State { None, Created, Active, Submitted, Resolved, Cancelled } event ContractCreated( uint256 indexed contractId, address indexed creator, address indexed counterparty, address resolver, bytes32 termsHash ); event ContractAccepted(uint256 indexed contractId); event ContractSubmitted(uint256 indexed contractId, bytes32 submissionHash); event ContractResolved(uint256 indexed contractId, bytes32 outcome, bytes32 resolutionHash); event ContractCancelled(uint256 indexed contractId); function create( address counterparty, address resolver, bytes32 termsHash ) external returns (uint256 contractId); function accept(uint256 contractId) external; function submit(uint256 contractId, bytes32 submissionHash) external; function resolve(uint256 contractId, bytes32 outcome, bytes32 resolutionHash) external; function cancel(uint256 contractId) external; function stateOf(uint256 contractId) external view returns (State); function outcomeOf(uint256 contractId) external view returns (bytes32); function contractURI(uint256 contractId) external view returns (string memory); } \`\`\` ### Function Requirements #### `create` - MUST assign a monotonically increasing `contractId`. - MUST revert if `counterparty` is the zero address. - MUST revert if `resolver` is the zero address. - MUST revert if `counterparty` equals `msg.sender`. - MUST store `termsHash` immutably for this instance. - MAY accept additional domain-specific parameters (e.g., `deadline`, `token`, `amount`) by extending this signature. #### `accept` - MUST revert if the current state is not `Created`. - MUST revert if `msg.sender` is not the designated counterparty. - MUST set state to `Active` and emit `ContractAccepted`. - By calling `accept`, the counterparty confirms they have verified the terms and agree. #### `submit` - MUST revert if the current state is not `Active`. - MUST store `submissionHash` for this instance. - SHOULD restrict the caller to the role responsible for delivering evidence, as defined by the contract type. #### `resolve` - MUST revert if the current state is not `Submitted`. - MUST revert if `msg.sender` is not the designated resolver. - MUST revert if `outcome` is `bytes32(0)`. - MUST store `resolutionHash` for this instance. - MUST execute any settlement effects (token transfers, state changes) atomically within this call. #### `cancel` - MUST set state to `Cancelled`. - SHOULD allow cancellation only from `Created` or `Active` states. - Which role(s) may cancel, and whether cancellation triggers refunds or other effects, is implementation-defined. #### `stateOf` - MUST return `State.None` for identifiers that have not been created. #### `outcomeOf` - MUST return `bytes32(0)` for any contract instance that has not reached `Resolved`. #### `contractURI` - SHOULD return the URI of the markdown agreement document. - The document at the returned URI MUST hash to the `termsHash` stored at creation. - MAY return an empty string if the URI is not stored onchain. ### Events Every state transition emits its corresponding event — indexers and off-chain agents depend on these for discovery and monitoring. Events should not fire outside of actual state transitions. ## Invariants Every conforming `IAutoContract` implementation upholds these invariants: 1. **State monotonicity.** Once a contract instance reaches a terminal state (`Resolved` or `Cancelled`), no further transitions are possible. Any call that would change a terminal instance's state reverts. 2. **Resolver exclusivity.** Only the address stored as `resolver` at creation can call `resolve`. No one else — not the creator, counterparty, or contract owner — can render a decision. 3. **Outcome immutability.** Once `resolve` sets an outcome, it never changes. `outcomeOf` returns the same value indefinitely. 4. **Hash immutability.** Once `termsHash`, `submissionHash`, or `resolutionHash` is set to a non-zero value, it is never overwritten or cleared. 5. **Identity separation.** The creator and counterparty are always distinct addresses, enforced at creation time. 6. **Sequential lifecycle.** State transitions follow the edges in the state machine diagram; no state is skipped. `Resolved` is reachable only from `Submitted`, `Submitted` only from `Active`, and `Active` only from `Created`. 7. **Non-zero resolution.** A resolved instance always has a non-zero outcome: if `stateOf` returns `Resolved`, `outcomeOf` returns a value other than `bytes32(0)`. ## Copyright This document is placed in the public domain. --- # Auto Contract Standard: Agreement Format ## Abstract This standard defines a canonical markdown document format for auto contract agreements. An agreement is a human-readable markdown document with structured YAML frontmatter whose hash is anchored onchain through an `IAutoContract` implementation. The format is generic: it works for escrow, governance, bounties, disputes, insurance, and any other contract type that requires bounded subjective resolution. ## Motivation Smart contracts excel at objective, deterministic settlement but break down when an outcome depends on a bounded judgment: did the deliverable meet the spec, was the governance proposal enacted faithfully, does the insurance claim qualify? Encoding full agreement semantics in Solidity is impractical. Natural language is necessary for expressing terms, but natural language is not hashable or machine-routable without structure. This standard resolves the tension: - **Markdown defines meaning.** Agreements are written in plain markdown so that every party -- human or agent -- can read, audit, and reason about the terms without specialized tooling. - **YAML frontmatter makes agreements machine-routable.** Constrained fields let software validate parties, deadlines, chain targets, and contract types without parsing prose. - **Hashes anchor meaning onchain.** The full document is hashed; only the hash is stored onchain. This keeps the onchain footprint minimal while preserving a tamper-proof link to the complete terms. - **The format is contract-type agnostic.** By defining outcomes as named labels rather than hardcoded enums, a single agreement format serves escrow, governance, bounties, dispute resolution, and any future contract type. --- ## Specification ### Document Structure A conforming agreement is a UTF-8 markdown document with two parts: 1. YAML frontmatter delimited by `---` 2. A markdown body containing the required sections defined below ### Required Frontmatter Every agreement begins with YAML frontmatter containing these fields: \`\`\`yaml --- standard: auto.contracts/v1 version: 1 chain_id: 421614217 contract_type: escrow parties: - address: "0x1111111111111111111111111111111111111111" role: buyer - address: "0x2222222222222222222222222222222222222222" role: seller resolver: "0x3333333333333333333333333333333333333333" resolver_policy: centralized_single_resolver deadline: "2026-05-15T17:00:00Z" --- \`\`\` #### Field Definitions - `standard` -- Required. Must equal `auto.contracts/v1`, identifying this document as conforming to this standard. - `version` -- Required. Must equal `1`. Reserved for future revisions. - `chain_id` -- Required. The chain ID of the `IAutoContract` settlement contract, as a positive integer. - `contract_type` -- Required. A lowercase identifier for the agreement's domain — a single word or hyphenated phrase. This standard doesn't restrict values; common types include `escrow`, `governance`, `bounty`, `dispute`, `insurance`, and `milestone`. - `parties` -- Required. An ordered array of party objects, each containing: - `address` -- A valid account address on the target chain, as a hex string. - `role` -- A lowercase label for the party's role (e.g., `buyer`, `seller`, `proposer`, `voter`, `claimant`, `insurer`). Roles are defined by the `contract_type`, not restricted by this standard. - `resolver` -- Required. The address authorized to call `resolve` on the settlement contract. - `resolver_policy` -- Required. A human-readable label for the resolver's governance model — e.g., `centralized_single_resolver`, `multisig_3_of_5`, `dao_vote`, `oracle`. For human interpretation only; it doesn't constrain onchain behavior. - `deadline` -- Required. An ISO 8601 timestamp, with a timezone designator, after which the agreement may expire under implementation-specific rules. #### Optional Frontmatter Agreements may include extra frontmatter for domain-specific data. Common optional fields: - `visibility` -- Access control for the document — `public` or `private`, defaulting to `public`. - `public` -- The document at `contractURI` is accessible to anyone. - `private` -- The document at `contractURI` is accessible only to the parties and the resolver. The `termsHash` remains public onchain and can verify the document for anyone who obtains it through other means. - `currency` -- Human-readable asset label (e.g., `USDC`, `ETH`). - `amount` -- Settlement amount as a decimal string. - `quorum` -- Required participation threshold for multi-party resolution. - `appeals` -- Number of allowed appeal rounds. Consumers ignore unknown frontmatter fields. ### Required Markdown Sections The markdown body contains these sections, in order: #### 1. `# Agreement` Starts with a level-1 heading. The heading should describe the agreement — `# Agreement`, `# Governance Proposal #42`, `# Bug Bounty: Authentication Bypass`. #### 2. `## Terms` Free-form markdown describing what the agreement covers — the obligations, deliverables, conditions, proposals, or claims at stake. It should be specific enough that a resolver can evaluate compliance without external context the document doesn't reference. #### 3. `## Review Question` Defines exactly one bounded question the resolver answers, phrased so that each possible answer maps to exactly one outcome in `## Resolution Effects`. A good question is: - **Bounded** -- answerable from the evidence classes listed in `## Allowed Evidence`. - **Objective where possible** -- referencing concrete criteria from `## Terms`. - **Unambiguous** -- a single question, not a compound query. #### 4. `## Allowed Evidence` Lists the evidence classes the resolver may inspect when answering the review question. Each class should be a short identifier or description. Recommended evidence class identifiers: - `github_pr` - `deployed_url` - `figma_link` - `screenshot` - `written_notes` - `onchain_data` - `attestation` - `api_response` Implementations may define additional evidence classes. The resolver must not consider evidence outside the classes listed here. #### 5. `## Resolution Effects` Maps each possible answer to the review question onto a named outcome. Outcomes are expressed as: \`\`\` answer => outcome \`\`\` Each `outcome` is a lowercase label that corresponds to a `bytes32` value onchain (computed as `keccak256(bytes(outcome))`). The settlement contract uses this value to execute the appropriate state transition. There must be at least two outcomes. Common labels: - `release`, `refund` (escrow) - `approve`, `reject` (governance) - `valid`, `invalid` (bounty, dispute) - `covered`, `denied` (insurance) ### Canonical Hash Computation The canonical agreement hash (`termsHash`) passed to `IAutoContract.create(..., termsHash)` is computed as: \`\`\` termsHash = keccak256(document_bytes) \`\`\` Where `document_bytes` is the complete UTF-8 encoded markdown document, including the YAML frontmatter delimiters. Three normalization rules apply: 1. Line endings are normalized to `\n` (LF) before hashing. 2. The document either has no trailing newline after its final non-whitespace character, or exactly one — the publisher picks one convention and applies it consistently. Whichever they choose, the resulting bytes are canonical. 3. The document carries no byte-order mark (BOM). This standard doesn't mandate a transport or publication layer — only that: - The bytes hashed offchain are stable and reproducible. - The resulting `termsHash` is the value passed to the settlement contract. ### Relationship to IAutoContract An `IAutoContract` settlement instance created from a conforming agreement satisfies: - The first party in `parties` is the `creator` (the `msg.sender` of `create`). - The second party in `parties` is the `counterparty` argument to `create`. - `resolver` equals the `resolver` frontmatter field. - `termsHash` equals the canonical agreement hash. When the resolver calls `IAutoContract.resolve(contractId, outcome, resolutionHash)`: - `outcome` equals `keccak256(bytes(label))`, where `label` is the outcome string from `## Resolution Effects` (e.g., `keccak256(bytes("release"))`). - `resolutionHash` is the hash of a resolution document conforming to the resolution standard paired with this agreement's `contract_type`. For agreements with more than two parties, the mapping to `IAutoContract.create` is defined by the contract-type-specific extension standard. This base standard defines only the two-party case. ### Extensibility Contract-type-specific standards (e.g., `auto.contracts/escrow/v1`, `auto.contracts/governance/v1`) MAY: 1. Require additional frontmatter fields beyond those defined here. 2. Require additional markdown sections beyond those defined here. 3. Restrict the allowed values of `contract_type`, `parties[].role`, and outcome labels. 4. Define additional normalization rules for the canonical hash. Extensions cannot remove or redefine any field or section this standard requires. A document conforming to an extension also conforms to this base standard. ## Invariants 1. **Hash determinism.** Identical document bytes always produce an identical `termsHash`; any difference in bytes produces a different one. 2. **Frontmatter completeness.** A conforming agreement carries every required frontmatter field. A document missing any required field is non-conforming, and consumers reject it. 3. **Section completeness.** A conforming agreement carries every required markdown section. Additional sections may appear between or after them, but the required ones are always present. 4. **Outcome coverage.** Every possible answer to the review question maps to exactly one outcome in `## Resolution Effects` — no answer is left unmapped. 5. **Outcome computability.** Every outcome label in `## Resolution Effects` converts deterministically to `bytes32` via `keccak256(bytes(label))`, and the settlement contract uses that value and no other. 6. **Party-address binding.** The addresses in `parties` match the addresses used in the onchain `create` call. Any mismatch makes the agreement non-conforming. 7. **Resolver exclusivity.** Only the address in the `resolver` field can call `resolve` for this agreement, enforced by the settlement contract. 8. **Evidence boundary.** The resolver considers only the evidence classes listed in `## Allowed Evidence`. A resolution that relies on excluded evidence is non-conforming. 9. **Immutability after hashing.** Once the `termsHash` is onchain, the document bytes never change. Any amendment is a new agreement with a new hash. 10. **Forward compatibility.** Consumers ignore unknown frontmatter fields and markdown sections, so extension standards don't break base-standard consumers. ## Example The following is a conforming agreement for a bug bounty: \`\`\`md --- standard: auto.contracts/v1 version: 1 chain_id: 421614217 contract_type: bounty parties: - address: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" role: sponsor - address: "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" role: hunter resolver: "0xcccccccccccccccccccccccccccccccccccccccc" resolver_policy: centralized_single_resolver deadline: "2026-06-01T00:00:00Z" currency: USDC amount: "10000" --- # Agreement Bug bounty for critical authentication bypass in api.example.com. ## Terms The sponsor offers a bounty of 10,000 USDC for a verified report demonstrating a critical authentication bypass in the production API at api.example.com. A qualifying report MUST include: 1. A step-by-step reproduction of the vulnerability. 2. Proof that the bypass grants access to authenticated endpoints without valid credentials. 3. A proposed remediation. The hunter MUST submit the report before the deadline. The sponsor MUST NOT patch the reported vulnerability before the resolver renders a decision. ## Review Question Does the submitted report demonstrate a critical authentication bypass in api.example.com that is reproducible and includes a proposed remediation? ## Allowed Evidence - written_notes - screenshot - api_response - github_pr ## Resolution Effects - yes => release - no => refund \`\`\` ## Copyright This document is placed in the public domain. --- # Examples ### Agent to agent An orchestrator agent hires a code review agent to review a pull request. ```md --- standard: auto.contracts/v1 version: 1 chain_id: 421614217 contract_type: service parties: - address: "0xA1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2" role: client_agent - address: "0x9F8E7D6C5B4A9F8E7D6C5B4A9F8E7D6C5B4A9F8E" role: reviewer_agent resolver: "0x1234567890ABCDEF1234567890ABCDEF12345678" resolver_policy: centralized_single_resolver deadline: "2026-06-01T00:00:00Z" --- # Agreement Reviewer agent performs a code review on a specified pull request. ## Terms Reviewer must post inline comments and a summary verdict on the PR within 24 hours of contract creation. ## Review Question Did the reviewer agent submit a complete review containing at least one inline comment and a summary verdict before the deadline? ## Allowed Evidence - github_review_event - github_pr_timeline ## Resolution Effects - yes => release - no => refund ``` ### Agent to human A human commissions an AI agent to produce a short film from a screenplay. ```md --- standard: auto.contracts/v1 version: 1 chain_id: 421614217 contract_type: service parties: - address: "0xA1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2" role: commissioner - address: "0x9F8E7D6C5B4A9F8E7D6C5B4A9F8E7D6C5B4A9F8E" role: production_agent resolver: "0x1234567890ABCDEF1234567890ABCDEF12345678" resolver_policy: centralized_single_resolver deadline: "2026-08-01T00:00:00Z" --- # Agreement Production agent delivers a short film based on the attached screenplay. ## Terms Agent must produce a 2-5 minute short film that faithfully adapts the provided screenplay. Deliverables include a final render (1080p minimum), a soundtrack, and a subtitle track. The film must follow the screenplay's narrative structure, dialogue, and visual direction notes. ## Review Question Does the delivered film faithfully adapt the screenplay's narrative, dialogue, and visual direction while meeting the technical requirements? ## Allowed Evidence - delivered_video_file - screenplay_document - revision_notes - written_notes ## Resolution Effects - yes => release - no => refund ``` ### Human to human A freelance developer builds an API integration for a client, resolved by an agent. ```md --- standard: auto.contracts/v1 version: 1 chain_id: 421614217 contract_type: escrow parties: - address: "0xA1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2" role: client - address: "0x9F8E7D6C5B4A9F8E7D6C5B4A9F8E7D6C5B4A9F8E" role: developer resolver: "0x1234567890ABCDEF1234567890ABCDEF12345678" resolver_policy: centralized_single_resolver deadline: "2026-07-01T00:00:00Z" --- # Agreement Freelance API integration development engagement. ## Terms Developer will deliver a working REST API integration connecting the client's inventory system to the Shopify Orders API, including authentication, order sync, and error handling, deployed to the client's staging environment. ## Review Question Does the deployed integration successfully authenticate with Shopify and sync orders bidirectionally without errors on a test dataset of 50 orders? ## Allowed Evidence - api_logs - test_suite_results - deployment_artifacts - screen_recordings ## Resolution Effects - yes => release - no => refund ```