ERC-8316: Programmable Settlement Locks

I’m preparing to open a PR for a new ERC tentatively titled “Programmable Settlement Locks”, and wanted to start a thread first to introduce the proposal and provide a place for discussion.

Context

The proposal defines a minimal interface for value-bearing contracts to expose a common lock lifecycle: creation, update, delegation, spending, cancellation, and inspection.

The primary use case is atomic settlement across systems that do not share the same asset model or visibility assumptions. This includes conventional token contracts such as ERC-20, shielded or private token systems, zero-knowledge proof based transfers, externally validated state transitions, and other value-bearing contracts where the details of an operation may not be fully visible on-chain.

Proposal summary

The core idea is a standardized settlement object, rather than a uniform token model.

A programmable settlement lock represents a prepared value-bearing operation with a single current spender, committed spend and cancel paths, and delegation of finalization authority.

The intended shape of the interface is roughly:

interface IERCXXXX {
   function createLock(...) external returns (bytes32 lockId);
   function updateLock(bytes32 lockId, ...) external;
   function delegateLock(bytes32 lockId, address newSpender, ...) external;
   function spendLock(bytes32 lockId, ...) external;
   function cancelLock(bytes32 lockId, ...) external;

   function getLock(bytes32 lockId) external view returns (...);
   function isLockActive(bytes32 lockId) external view returns (bool);
}

The implementing contract is responsible for defining exactly what the lock means, how arguments are encoded, how commitments are constructed, and how supplied execution arguments are validated.

This allows a single executor, such as a coordinating smart contract, to settle many such locks in a uniform manner, even when they are tied to assets or value systems with very different internal construction.

The proposal is intended to support flows where a party prepares an operation on its own asset or value system, delegates control of that prepared operation to another party or coordinating contract, and allows the delegated spender to finalize it only through the predefined spend or cancel path.

Review focus

My plan is to open the PR with the complete specification rather than reproducing or summarizing it here. The most useful discussion will likely be against the full proposal.

Initial feedback is welcome on the general framing, related settlement patterns, and major token or value-system examples that should be considered. I’ll link back here once the PR is open to allow for more detailed discussion on the specifics.

2 Likes

PR for the proposal is here: Add ERC: Programmable Settlement Locks by awrichar · Pull Request #1840 · ethereum/ERCs · GitHub

This is a super interesting problem that you’re tackling with this ERC. There’s a good bit of conversation happening around how various ERCs that are orthogonally related to this area are composable with each other, and I think this contribution would be very welcome in that regard.

I contributed to ERC-8312 (Bounded Agent Actions), and this feels largely complementary rather than overlapping.

My current (albeit preliminary) mental model is that the two proposals answer different questions:

  • ERC-8316: “What value-bearing operation is being prepared and eventually settled?”

  • ERC-8312: “How much of an agent’s bounded mandate has been consumed across all actions so far?”

One is a settlement primitive, the other is an aggregate metering primitive if that makes sense.

I could imagine them composing quite naturally. For example: an agent operating under a bounded mandate (via 8312) might prepare multiple settlement locks over time. Each successful spendLock() could become the witness that advances the agent’s bounded-action cursor. The settlement lock finalizes a single operation, while the cursor records the cumulative authority consumed by all such operations.

Something like this . . .

Bounded Action Envelope
        │
        ├── Settlement Lock A → spend
        ├── Settlement Lock B → spend
        ├── Settlement Lock C → cancel
        └── Settlement Lock D → spend

Cursor = aggregate authority consumed

I think what makes this useful is that avoids forcing settlement objects to become policy objects iykwim.

One question that occurred to me while reading the proposal: could a settlement lock optionally carry an (chainId, registry, envelopeId) reference (or equivalent) as opaque metadata? That would allow a coordinating contract to update both the settlement lifecycle and the bounded-action cursor atomically, without either ERC depending directly on the other.

From my perspective, one potential approach to layering would be as follows:

  • ERC-7710 / ERC-7715: delegation and authorization

  • ERC-8312: aggregate authority metering

  • ERC-8316: settlement object lifecycle

  • ERC-8301: workflow orchestration

Each layer answers a different question which makes the composition cleaner than trying to merge the responsibilities into a single primitive. I’d love to know what you think.

1 Like

@orbmis yes, totally agreed on composability - I think it’s always most useful when each standard focuses on one specific piece like you’ve described.

I hadn’t given a lot of thought to agentic flows specifically, but it’s actually an interesting angle here. I can think of multiple ways agents could interact with settlement locks:

  1. Agent as lock creator (creates locks to be settled later)
  2. Agent as delegated spender (settles locks that were delegated to it)
  3. Agent as lock coordinator operator (finalizes multiple locks that were delegated to a coordinator contract)

All of those provide different ways that humans or policies could gate the actions that the agent can execute. As you said, the settlement object and the policy object remain decoupled.


On your question about lock metadata - yes, there’s a lot of flexibility (intentionally) in what a lock could represent or carry. We’ve proved out a handful of examples already (just need to clean up a repo with some reference implementations). But for a few examples:

The simplest lock is something like an ERC-20 contract extension for locked transfers: locks can be created with an amount and recipient, and the lock holds those funds (essentially an escrow), and will either send or return them (spend or cancel).

For a shielded token (like a Zcash or Railgun style), a lock extension would mean setting aside some value, preparing the proofs/commitments needed to spend/cancel, and then allowing the designated spender to choose the outcome (providing the appropriate proof/args). Functionally similar to an ERC-20 escrow, but totally different logic.

Of course locks can represent many other things as well - spending tokens is just the most obvious example.

But maybe the point is that each implementing contract has to store some info about each lock it creates, including what the lock “is” (details and metadata) as well as what the lock can “do” (spend/cancel commitments). We considered whether LockInfo should include a queryable “content” or “metadata” field. Ultimately we left that off the standard interface for now, since it would just be opaque bytes… but I think any implementation would still need to store metadata about each lock (whether it’s standardized or implementation-specific).

A reference repository is now live here: GitHub - kaleido-io/erc-8316: Reference information and samples to support ERC-8316 · GitHub