StakeTable
Inherits: Initializable, InitializedAt, OwnableUpgradeable, UUPSUpgradeable
Title: Ethereum L1 component of the Espresso Global Confirmation Layer (GCL) stake table.
All functions are marked as virtual so that future upgrades can override them.
State Variables
lightClient
Reference to the light client contract.
Currently unused but will be used for slashing therefore already included in the contract.
ILightClient public lightClient
token
The staking token contract.
ERC20 public token
validators
All validators the contract knows about.
mapping(address account => Validator validator) public validators
blsKeys
BLS keys that have been seen by the contract
to simplify the reasoning about what keys and prevent some errors due to misconfigurations of validators the contract currently marks keys as used and only allow them to be used once. This for example prevents callers from accidentally registering the same BLS key twice.
mapping(bytes32 blsKeyHash => bool used) public blsKeys
validatorExits
Validators that have exited and the time at which delegators can claim their funds.
mapping(address validator => uint256 unlocksAt) public validatorExits
delegations
Currently active delegation amounts.
mapping(address validator => mapping(address delegator => uint256 amount)) public delegations
undelegations
Delegations held in escrow that are to be unlocked at a later time.
mapping(address validator => mapping(address delegator => Undelegation)) public undelegations
exitEscrowPeriod
The time (seconds) the contract will hold funds after undelegations are requested. Must allow ample time for node to exit active validator set and slashing evidence to be submitted.
uint256 public exitEscrowPeriod
Functions
constructor
since the constructor initializes storage on this contract we disable it
storage is on the proxy contract since it calls this contract via delegatecall
Note: oz-upgrades-unsafe-allow: constructor
constructor() ;
initialize
function initialize(
address _tokenAddress,
address _lightClientAddress,
uint256 _exitEscrowPeriod,
address _timelock
) public initializer;
initializeState
Initialize the state of the contract
function initializeState(
address _tokenAddress,
address _lightClientAddress,
uint256 _exitEscrowPeriod
) internal;
Parameters
| Name | Type | Description |
|---|---|---|
_tokenAddress | address | The address of the staking token |
_lightClientAddress | address | The address of the light client |
_exitEscrowPeriod | uint256 | The exit escrow period. Set to uint64.max to disable the exit escrow period. |
getVersion
Use this to get the implementation contract version
function getVersion()
public
pure
virtual
returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);
Returns
| Name | Type | Description |
|---|---|---|
majorVersion | uint8 | The major version of the contract |
minorVersion | uint8 | The minor version of the contract |
patchVersion | uint8 | The patch version of the contract |
_authorizeUpgrade
only the timelock can authorize an upgrade
function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner;
renounceOwnership
Prevent renouncing ownership to preserve governance control.
Override renounceOwnership() to revert, preventing accidental or malicious ownership renunciation
function renounceOwnership() public virtual override onlyOwner;
_hashBlsKey
Computes a hash value of some G2 point.
function _hashBlsKey(BN254.G2Point memory blsVK) public pure returns (bytes32);
Parameters
| Name | Type | Description |
|---|---|---|
blsVK | BN254.G2Point | BLS verification key in G2 |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bytes32 | keccak256(blsVK) |
ensureValidatorActive
function ensureValidatorActive(address validator) internal view;
ensureValidatorNotRegistered
function ensureValidatorNotRegistered(address validator) internal view;
ensureNewKey
function ensureNewKey(BN254.G2Point memory blsVK) internal view;
ensureNonZeroSchnorrKey
function ensureNonZeroSchnorrKey(EdOnBN254.EdOnBN254Point memory schnorrVK) internal pure;
registerValidator
Register a validator in the stake table
The function will revert if
- the validator is already registered
- the schnorr key is zero
- if the bls signature verification fails (this prevents rogue public-key attacks).
- the commission is > 100%
No validity check on schnorrVK due to gas cost of Rescue hash, UIs should perform
checks where possible and alert users.
function registerValidator(
BN254.G2Point memory blsVK,
EdOnBN254.EdOnBN254Point memory schnorrVK,
BN254.G1Point memory blsSig,
uint16 commission
) external virtual;
Parameters
| Name | Type | Description |
|---|---|---|
blsVK | BN254.G2Point | The BLS verification key |
schnorrVK | EdOnBN254.EdOnBN254Point | The Schnorr verification key (as the auxiliary info) |
blsSig | BN254.G1Point | The BLS signature that authenticates the ethereum account this function is called from |
commission | uint16 | in % with 2 decimals, from 0.00% (value 0) to 100% (value 10_000) |
deregisterValidator
Deregister a validator
function deregisterValidator() public virtual;
delegate
Delegate to a validator
function delegate(address validator, uint256 amount) public virtual;
Parameters
| Name | Type | Description |
|---|---|---|
validator | address | The validator to delegate to |
amount | uint256 | The amount to delegate |
undelegate
Undelegate from a validator
function undelegate(address validator, uint256 amount) public virtual;
Parameters
| Name | Type | Description |
|---|---|---|
validator | address | The validator to undelegate from |
amount | uint256 | The amount to undelegate |
claimWithdrawal
Withdraw previously delegated funds after an undelegation.
function claimWithdrawal(address validator) public virtual;
Parameters
| Name | Type | Description |
|---|---|---|
validator | address | The validator to withdraw from |
claimValidatorExit
Withdraw previously delegated funds after a validator has exited
function claimValidatorExit(address validator) public virtual;
Parameters
| Name | Type | Description |
|---|---|---|
validator | address | The validator to withdraw from |
updateConsensusKeys
Update the consensus keys for a validator
This function is used to update the consensus keys for a validator
This function can only be called by the validator itself when it hasn’t exited
The validator will need to give up either its old BLS key and/or old Schnorr key
The validator will need to provide a BLS signature to prove that the account owns the new BLS key
function updateConsensusKeys(
BN254.G2Point memory newBlsVK,
EdOnBN254.EdOnBN254Point memory newSchnorrVK,
BN254.G1Point memory newBlsSig
) external virtual;
Parameters
| Name | Type | Description |
|---|---|---|
newBlsVK | BN254.G2Point | The new BLS verification key |
newSchnorrVK | EdOnBN254.EdOnBN254Point | The new Schnorr verification key |
newBlsSig | BN254.G1Point | The BLS signature that the account owns the new BLS key |
Events
ValidatorRegistered
A registration of a new validator.
Signals to the confirmation layer that a new validator is ready to receive delegations in the stake table contract. The confirmation layer uses this event to keep track of the validator’s keys for the stake table.
The commission is in % with 2 decimals, from 0.00% (value 0) to 100% (value 10_000).
A validator registration is only valid if the BLS and Schnorr signature are valid. The GCL must verify this and otherwise discard the validator registration when it processes the event. The contract cannot verify the validity of the registration event and delegators will be able to deposit as soon as this event is emitted. In the event that a delegator delegates to an invalid validator the delegator can withdraw the delegation again in the same way they can withdraw other delegations.
UIs should do their best to prevent invalid, or duplicate registrations.
The verification key of the BLS keypair used for consensus signing is a
BN254.G2Point.
The verification key of the state signing schnorr keypair is an
EdOnBN254.EdOnBN254Point.
event ValidatorRegistered(
address indexed account,
BN254.G2Point blsVk,
EdOnBN254.EdOnBN254Point schnorrVk,
uint16 commission
);
ValidatorExit
A validator initiated an exit from stake table
All funds delegated to this validator are marked for withdrawal. Users can no longer
delegate to this validator. Their previously delegated funds are automatically undelegated.
After exitEscrowPeriod elapsed, delegators can claim the funds delegated to the exited
validator via claimValidatorExit.
The GCL removes this validator and all its delegations from the active validator set.
event ValidatorExit(address indexed validator);
Delegated
A Delegator delegated funds to a validator.
The tokens are transferred to the stake table contract.
The GCL adjusts the weight for this validator and the delegators delegation associated with it.
event Delegated(address indexed delegator, address indexed validator, uint256 amount);
Undelegated
A delegator undelegation funds from a validator.
The tokens are marked to be unlocked for withdrawal.
The GCL needs to update the stake table and adjust the weight for this validator and the delegators delegation associated with it.
event Undelegated(address indexed delegator, address indexed validator, uint256 amount);
ConsensusKeysUpdated
A validator updates their signing keys.
Similarly to registration events, the correctness cannot be fully determined by the contracts.
The confirmation layer needs to update the stake table with the new keys.
event ConsensusKeysUpdated(
address indexed account, BN254.G2Point blsVK, EdOnBN254.EdOnBN254Point schnorrVK
);
Withdrawal
A delegator claims unlocked funds.
This event is not relevant for the GCL. The events that remove stake from the stake
table are Undelegated and ValidatorExit.
event Withdrawal(address indexed account, uint256 amount);
Errors
ValidatorAlreadyRegistered
A user tries to register a validator with the same address
error ValidatorAlreadyRegistered();
ValidatorInactive
error ValidatorInactive();
ValidatorAlreadyExited
A validator has already exited.
error ValidatorAlreadyExited();
ValidatorNotExited
A validator has not exited yet.
error ValidatorNotExited();
PrematureWithdrawal
error PrematureWithdrawal();
InsufficientAllowance
error InsufficientAllowance(uint256, uint256);
InsufficientBalance
error InsufficientBalance(uint256);
NothingToWithdraw
error NothingToWithdraw();
InvalidSchnorrVK
error InvalidSchnorrVK();
BlsKeyAlreadyUsed
The BLS key has been previously registered in the contract.
error BlsKeyAlreadyUsed();
InvalidCommission
The commission value is invalid.
error InvalidCommission();
ZeroAddress
Contract dependencies initialized with zero address.
error ZeroAddress();
UndelegationAlreadyExists
An undelegation already exists for this validator and delegator.
error UndelegationAlreadyExists();
ZeroAmount
A zero amount would lead to a no-op.
error ZeroAmount();
OwnershipCannotBeRenounced
Attempted to renounce ownership which would break governance controls.
error OwnershipCannotBeRenounced();
ExitEscrowPeriodInvalid
The exit escrow period is invalid (either too short or too long)
error ExitEscrowPeriodInvalid();
Structs
Validator
Represents an Espresso validator and tracks funds currently delegated to them.
The delegatedAmount excludes funds that are currently marked for withdrawal via
undelegation or validator exit.
struct Validator {
uint256 delegatedAmount;
ValidatorStatus status;
}
Undelegation
Tracks an undelegation from a validator.
struct Undelegation {
uint256 amount;
uint256 unlocksAt;
}
Enums
ValidatorStatus
The status of a validator.
By default a validator is in the Unknown state. This means it has never registered. Upon
registration the status will become Active and if the validator deregisters its status
becomes Exited.
enum ValidatorStatus {
Unknown,
Active,
Exited
}