A simple commit interface to support commit-reveal scheme which provides only a commit
method but no reveal method, allowing implementations to integrate this interface
with arbitrary reveal methods such as vote
or transfer
.
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
Interfaces referenced in this specification are as follows:
pragma solidity >=0.7.0 <0.9.0;
// The EIP-165 identifier of this interface is 0xf14fcbc8
interface IERC_COMMIT_CORE {
function commit(bytes32 _commitment) payable external;
}
pragma solidity >=0.7.0 <0.9.0;
// The EIP-165 identifier of this interface is 0x67b2ec2c
interface IERC_COMMIT_GENERAL {
event Commit(
uint256 indexed _timePoint,
address indexed _from,
bytes32 indexed _commitment,
bytes _extraData);
function commitFrom(
address _from,
bytes32 _commitment,
bytes calldata _extraData)
payable external returns(uint256 timePoint);
}
IERC_COMMIT_CORE
interface.IERC_COMMIT_GENERAL
interface.IERC_COMMIT_GENERAL
interface MUST accept commit(_commitment)
as equivalent to commitFrom(msg.sender, _commitment, [/*empty array*/])
.timePoint
return value of commitFrom
is RECOMMENDED to use block.timestamp
or block.number
or a number that indicates the ordering of different commitments. When commitFrom
is being called.A compliant contract that implements IERC_COMMIT_GENERAL
MUST emit event Commit
when a commitment is accepted and recorded. In the parameter of both Commit
and the commitFrom
method, the _timePoint
is a time-point-representing value that represents ordering of commitments in which a latter commitment will always have a greater or equal value than a former commitment, such as block.timestamp
or block.number
or other time scale chosen by implementing contracts.
The extraData
is reserved for future behavior extension. If the _from
is different from the TX signer, it is RECOMMENDED that compliant contract SHOULD validate signature for _from
. For EOAs this will be validating its ECDSA signatures on chain. For smart contract accounts, it is RECOMMENDED to use EIP-1271 to validate the signatures.
One or more methods of a compliant contract MAY be used for reveal.
But there MUST be a way to supply an extra field of secret_salt
, so that committer can later open the secret_salt
in the reveal TX that exposes the secret_salt
. The size and location of secret_salt
is intentionally unspecified in this EIP to maximize flexibility for integration.
One design options is that we can attach a Commit Interface to any individual ERCs such as voting standards or token standards. We choose to have a simple and generalize commit interface so all ERCs can be extended to support commit-reveal without changing their basic method signatures.
The key derived design decision we made is we will have a standardized commit
method without a standardized reveal
method, making room for customized reveal method or using commit
with existing standard.
We chose to have a simple one parameter method of commit
in our Core interface to make it fully backward compatible with a few prior-adoptions e.g. ENS
We also add a commitFrom
to easy commitment being generated off-chain and submitted by some account on behalf by another account.
This EIP is backward compatible with all existing ERCs method signature that has extraData. New EIPs can be designed with an extra field of "salt" to make it easier to support this EIP, but not required.
The IERC_COMMIT_CORE
is backward compatible with ENS implementations and other existing prior-art.
In ENS registering process, currently inside of ETHRegistrarController
contract a commit function is being used to allow registerer fairly register a desire domain to avoid being front-run.
Here is how ENS uses commitment in its registration logic:
function commit(bytes32 commitment) public {
require(commitments[commitment] + maxCommitmentAge < now);
commitments[commitment] = now;
}
With this EIP it can be updated to
function commit(bytes32 commitment, bytes calldata data) public {
require(commitments[commitment] + maxCommitmentAge < now);
commitments[commitment] = now;
emit Commit(...);
}
secret_salt
, MUST be kept secret before they are revealed.secret_salt
must be cryptographically long enough and the random values used to generate secret_salt
must be cryptographically safe.secret_salt
. It's recommended for client applications to warn users who attempt to do so._timePoint
from the next transaction to be strictly greater than that of any previous transaction, block.timestamp
and block.number
are not reliable as two transactions could co-exist in the same block resulting in the same _timePoint
value. In such case, extra measures to enforce this strict monotonicity are required, such as the use of a separate sate variable in the contract to keep track of number of commits it receives, or to reject any second/other TX that shares the same block.timestamp
or block.number
.Copyright and related rights waived via CC0.