Interface for scheduling, executing and challenging contract executions based on off-chain approval
Abstract
ERC-3000 presents a basic on-chain spec for contracts to optimistically enact governance decisions made off-chain.
The standard is opinionated in defining the 6 entrypoint functions to contracts supporting the standard. But it allows for any sort of resolver mechanism for the challenge/response games characteristic of optimistic contracts.
While the authors currently believe resolving challenges using a subjective oracle is the right tradeoff, the standard has been designed such that changing to another mechanism is possible (a deterministic resolver like Optimism’s OVM uses), even allowing to hot-swap it in the same live instance.
Specification
Data structures
Some data structures are defined which are later used in the standard interfaces:
Given the data structures above, by taking advantage of the Solidity ABI encoder v2, we define four required functions and two optional functions as the interface for contracts to comply with ERC-3000.
All standard functions are expected to revert (whether to include error messages/revert reasons as part of the standard is yet to be determined) when pre-conditions are not met or an unexpected error occurs. On success, each function must emit its associated event once and only once.
abstractcontractIERC3000{/**
* @notice Schedules an action for execution, allowing for challenges and vetos on a defined time window
* @param container A Container struct holding both the paylaod being scheduled for execution and
the current configuration of the system
*/functionschedule(ERC3000Data.Containermemorycontainer)virtualpublicreturns(bytes32containerHash);eventScheduled(bytes32indexedcontainerHash,ERC3000Data.Payloadpayload,ERC3000Data.Collateralcollateral);/**
* @notice Executes an action after its execution delayed has passed and its state hasn't been altered by a challenge or veto
* @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and
the current configuration of the system
* should be a MUST payload.executor.exec(payload.actions)
*/functionexecute(ERC3000Data.Containermemorycontainer)virtualpublicreturns(bytes[]memoryexecResults);eventExecuted(bytes32indexedcontainerHash,addressindexedactor,bytes[]execResults);/**
* @notice Challenge a container in case its scheduling is illegal as per Config.rules. Pulls collateral and dispute fees from sender into contract
* @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and
the current configuration of the system
* @param reason Hint for case reviewers as to why the scheduled container is illegal
*/functionchallenge(ERC3000Data.Containermemorycontainer,bytesmemoryreason)virtualpublicreturns(uint256resolverId);eventChallenged(bytes32indexedcontainerHash,addressindexedactor,bytesreason,uint256resolverId,ERC3000Data.Collateralcollateral);/**
* @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling
* @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and
the current configuration of the system
* @param resolverId disputeId in the arbitrator in which the dispute over the container was created
*/functionresolve(ERC3000Data.Containermemorycontainer,uint256resolverId)virtualpublicreturns(bytes[]memoryexecResults);eventResolved(bytes32indexedcontainerHash,addressindexedactor,boolapproved);/**
* @dev OPTIONAL
* @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling
* @param payloadHash Hash of the payload being vetoed
* @param config A ERC3000Data.Config struct holding the config attached to the payload being vetoed
*/functionveto(bytes32payloadHash,ERC3000Data.Configmemoryconfig,bytesmemoryreason)virtualpublic;eventVetoed(bytes32indexedcontainerHash,addressindexedactor,bytesreason,ERC3000Data.Collateralcollateral);/**
* @dev OPTIONAL: implementer might choose not to implement (initial Configured event MUST be emitted)
* @notice Apply a new configuration for all *new* containers to be scheduled
* @param config A ERC3000Data.Config struct holding all the new params that will control the queue
*/functionconfigure(ERC3000Data.Configmemoryconfig)virtualpublicreturns(bytes32configHash);eventConfigured(bytes32indexedcontainerHash,addressindexedactor,ERC3000Data.Configconfig);}
Rationale
The authors believe that it is very important that this standard leaves the other open to any resolver mechanism to be implemented and adopted.
That’s why a lot of the function and variable names were left intentionally bogus to be compatible with future resolvers without changing the standard.
ERC-3000 should be seen as a public good of top of which public infrastrastructure will be built, being way more important than any particular implementation or the interests of specific companies or projects.
Security Considerations
The standard allows for the resolver for challenges to be configured, and even have different resolvers for coexisting scheduled payloads. Choosing the right resolver requires making the right tradeoff between security, time to finality, implementation complexity, and external dependencies.
Using a subjective oracle as resolver has its risks, since security depends on the crypto-economic properties of the system. For an analysis of crypto-economic considerations of Aragon Court, you can check the following doc.
On the other hand, implementing a deterministic resolver is prone to dangerous bugs given its complexity, and will rely on a specific version of the off-chain protocol, which could rapidly evolve while the standard matures and gets adopted.