Appearance
Abstract
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
.
Motivation
- support commit-reveal privacy for applications such as voting.
- make it harder for attackers for front-running, back-running or sandwich attacks.
Specification
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:
solidity
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);
}
A compliant contract MUST implement the
IERC_COMMIT_CORE
interface.A compliant contract SHOULD implement the
IERC_COMMIT_GENERAL
interface.A compliant contract that implements the
IERC_COMMIT_GENERAL
interface MUST acceptcommit(_commitment)
as equivalent tocommitFrom(msg.sender, _commitment, [/*empty array*/])
.The
timePoint
return value ofcommitFrom
is RECOMMENDED to useblock.timestamp
orblock.number
or a number that indicates the ordering of different commitments. WhencommitFrom
is being called.A compliant contract that implements
IERC_COMMIT_GENERAL
MUST emit eventCommit
when a commitment is accepted and recorded. In the parameter of bothCommit
and thecommitFrom
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 asblock.timestamp
orblock.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.
- It is RECOMMENDED for compliant contracts to implement EIP-165.
Rationale
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 standardizedreveal
method, making room for customized reveal method or usingcommit
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. ENSWe also add a
commitFrom
to easy commitment being generated off-chain and submitted by some account on behalf by another account.
Backwards Compatibility
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.
Reference Implementation
Commit with ENS Register as Reveal
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:
solidity
function commit(bytes32 commitment) public {
require(commitments[commitment] + maxCommitmentAge < now);
commitments[commitment] = now;
}
With this EIP it can be updated to
solidity
function commit(bytes32 commitment, bytes calldata data) public {
require(commitments[commitment] + maxCommitmentAge < now);
commitments[commitment] = now;
emit Commit(...);
}
Security Considerations
- Do not use the reference implementation in production. It is just for demonstration purposes.
- The reveal transactions and parameters, especially
secret_salt
, MUST be kept secret before they are revealed. - The length of
secret_salt
must be cryptographically long enough and the random values used to generatesecret_salt
must be cryptographically safe. - Users must NEVER reuse a used
secret_salt
. It's recommended for client applications to warn users who attempt to do so. - Contract implementations should consider deleting the commitment of a given sender immediately to reduce the chances of a replay attack or re-entry attack.
- Contract implementations may consider including the ordering of commitment received to add restrictions on the order of reveal transactions.
- There is potential for replay attacks across different chainIds or chains resulting from forks. In these cases, the chainId must be included in the generation of commitment. For applications with a higher risk of replay attacks, implementors should consider battle-tested and cryptographically-secure solutions such as EIP-712 to compose commitments before creating their own new solution.
- Proper time gaps are suggested if the purpose is to avoid frontrunning attacks.
- For compliant contract that requires the
_timePoint
from the next transaction to be strictly greater than that of any previous transaction,block.timestamp
andblock.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 sameblock.timestamp
orblock.number
.
Copyright
Copyright and related rights waived via CC0.