Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Espresso Network Smart Contracts

Smart contracts for the Espresso Network.

Upgradeable contracts use the frozen inheritance pattern: each new version (e.g. StakeTableV2) inherits from the previous version, preserving storage layout and ensuring upgrade safety.

Contracts

Interfaces

Libraries

Contents

Contents

ILightClient

Git Source

Functions

blocksPerEpoch

function blocksPerEpoch() external view returns (uint64);

IPlonkVerifier

Git Source

Title: The structs and interfaces for a specific flavor of TurboPlonk verifier.

Functions

verify

Verify a single TurboPlonk proofs.

function verify(
    VerifyingKey memory verifyingKey,
    uint256[] memory publicInput,
    PlonkProof memory proof
) external view returns (bool);

Parameters

NameTypeDescription
verifyingKeyVerifyingKeyThe Plonk verification key
publicInputuint256[]The public input fields
proofPlonkProofThe TurboPlonk proof

Returns

NameTypeDescription
<none>bool_ A boolean indicating successful verification, false otherwise

Structs

PlonkProof

struct PlonkProof {
    // the first 5 are 4 inputs and 1 output wire poly commmitments
    // i.e., batch_proof.wires_poly_comms_vec.iter()
    // wire0 is 32 bytes which is a pointer to BN254.G1Point
    BN254.G1Point wire0; // 0x00
    BN254.G1Point wire1; // 0x20
    BN254.G1Point wire2; // 0x40
    BN254.G1Point wire3; // 0x60
    BN254.G1Point wire4; // 0x80
    // the next one is the  product permutation poly commitment
    // i.e., batch_proof.prod_perm_poly_comms_vec.iter()
    BN254.G1Point prodPerm; // 0xA0
    // the next 5 are split quotient poly commmitments
    // i.e., batch_proof.split_quot_poly_comms
    BN254.G1Point split0; // 0xC0
    BN254.G1Point split1; // 0xE0
    BN254.G1Point split2; // 0x100
    BN254.G1Point split3; // 0x120
    BN254.G1Point split4; // 0x140
    // witness poly com for aggregated opening at `zeta`
    // i.e., batch_proof.opening_proof
    BN254.G1Point zeta; // 0x160
    // witness poly com for shifted opening at `zeta * \omega`
    // i.e., batch_proof.shifted_opening_proof
    BN254.G1Point zetaOmega; // 0x180
    // wire poly eval at `zeta`
    BN254.ScalarField wireEval0; // 0x1A0
    BN254.ScalarField wireEval1; // 0x1C0
    BN254.ScalarField wireEval2; // 0x1E0
    BN254.ScalarField wireEval3; // 0x200
    BN254.ScalarField wireEval4; // 0x220
    // extended permutation (sigma) poly eval at `zeta`
    // last (sigmaEval4) is saved by Maller Optimization
    BN254.ScalarField sigmaEval0; // 0x240
    BN254.ScalarField sigmaEval1; // 0x260
    BN254.ScalarField sigmaEval2; // 0x280
    BN254.ScalarField sigmaEval3; // 0x2A0
    // product permutation poly eval at `zeta * \omega`
    BN254.ScalarField prodPermZetaOmegaEval; // 0x2C0
}

VerifyingKey

struct VerifyingKey {
    uint256 domainSize; // 0x00
    uint256 numInputs; // 0x20
    // commitment to extended perm (sigma) poly
    BN254.G1Point sigma0; // 0x40
    BN254.G1Point sigma1; // 0x60
    BN254.G1Point sigma2; // 0x80
    BN254.G1Point sigma3; // 0xA0
    BN254.G1Point sigma4; // 0xC0
    // commitment to selector poly
    // first 4 are linear combination selector
    BN254.G1Point q1; // 0xE0
    BN254.G1Point q2; // 0x100
    BN254.G1Point q3; // 0x120
    BN254.G1Point q4; // 0x140
    // multiplication selector for 1st, 2nd wire
    BN254.G1Point qM12; // 0x160
    // multiplication selector for 3rd, 4th wire
    BN254.G1Point qM34; // 0x180
    // output selector
    BN254.G1Point qO; // 0x1A0
    // constant term selector
    BN254.G1Point qC; // 0x1C0
    // rescue selector qH1 * w_ai^5
    BN254.G1Point qH1; // 0x1E0
    // rescue selector qH2 * w_bi^5
    BN254.G1Point qH2; // 0x200
    // rescue selector qH3 * w_ci^5
    BN254.G1Point qH3; // 0x220
    // rescue selector qH4 * w_di^5
    BN254.G1Point qH4; // 0x240
    // elliptic curve selector
    BN254.G1Point qEcc; // 0x260
    // serialized G2 point in SRS (compressed, little-endian, 64 bytes)
    // we store the 64 bytes as 2 * bytes32 (first 32 bytes as `g2LSB`)
    // (G1 points in SRS are implicitly committed via poly commitments)
    bytes32 g2LSB; // 0x280
    bytes32 g2MSB; // 0x2A0
}

IRewardClaim

Git Source

This interface contains the methods, events and errors for claiming Espresso staking rewards.

This interface does not include administrative functionality of the RewardClaim contract.

Functions

claimRewards

Claim staking rewards

Obtain authData from the Espresso query service API.

function claimRewards(uint256 lifetimeRewards, bytes calldata authData) external;

Parameters

NameTypeDescription
lifetimeRewardsuint256Total earned lifetime rewards for the user @param
authDatabytesinputs required for authentication of lifetime rewards amount.

claimedRewards

Check amount of rewards claimed by a user

function claimedRewards(address claimer) external view returns (uint256);

totalClaimed

Total amount claimed by all users

function totalClaimed() external view returns (uint256);

Events

RewardsClaimed

User claimed rewards

event RewardsClaimed(address indexed user, uint256 amount);

Errors

InvalidAuthRoot

Unable to authenticate rewards against Light Client contract

error InvalidAuthRoot();

AlreadyClaimed

All available rewards already claimed

error AlreadyClaimed();

InvalidRewardAmount

Reward amount must be greater than zero

error InvalidRewardAmount();

DailyLimitExceeded

A claim would exceed the remaining daily capacity

error DailyLimitExceeded();

Contents

Transcript

Git Source

Functions

appendMessage

function appendMessage(TranscriptData memory self, bytes memory message) internal pure;

appendChallenge

function appendChallenge(TranscriptData memory self, uint256 challenge) internal pure;

appendCommitments

function appendCommitments(TranscriptData memory self, BN254.G1Point[] memory comms)
    internal
    pure;

appendCommitment

function appendCommitment(TranscriptData memory self, BN254.G1Point memory comm) internal pure;

getChallenge

function getChallenge(TranscriptData memory self) internal pure returns (uint256 ret);

appendVkAndPubInput

Append the verifying key and the public inputs to the transcript.

function appendVkAndPubInput(
    TranscriptData memory self,
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    uint256[] memory publicInput
) internal pure;

Parameters

NameTypeDescription
selfTranscriptData
verifyingKeyIPlonkVerifier.VerifyingKeyverifying key
publicInputuint256[]a list of field elements

appendProofEvaluations

Append the proof to the transcript. Only used for test purposes.

function appendProofEvaluations(
    TranscriptData memory self,
    IPlonkVerifier.PlonkProof memory proof
) internal pure;

Structs

TranscriptData

struct TranscriptData {
    bytes32 state;
    bytes transcript;
}

Contents

BLSSig

Git Source

test top This library implements the verification of the BLS signature scheme over the BN254 curve following the rust implementation at https://github.com/EspressoSystems/jellyfish/blob/e1e683c287f20160738e6e737295dd8f9e70577a/primitives/src/signatures/bls_over_bn254.rs

Functions

_uint256FromBytesLittleEndian

function _uint256FromBytesLittleEndian(uint8[] memory input) private pure returns (uint256);

expand

Takes a sequence of bytes and turn in into another sequence of bytes with fixed size. Equivalent of https://github.com/arkworks-rs/algebra/blob/1f7b3c6b215e98fa3130b39d2967f6b43df41e04/ff/src/fields/field_hashers/expander/mod.rs#L37

function expand(bytes memory message) internal pure returns (bytes memory);

Parameters

NameTypeDescription
messagebytesmessage to be “expanded”

Returns

NameTypeDescription
<none>bytesfixed size array of bytes

hashToField

Hash a sequence of bytes to a field element in Fq. Equivalent of https://github.com/arkworks-rs/algebra/blob/1f7b3c6b215e98fa3130b39d2967f6b43df41e04/ff/src/fields/field_hashers/mod.rs#L65

function hashToField(bytes memory message) internal pure returns (uint256);

Parameters

NameTypeDescription
messagebytesinput message to be hashed

Returns

NameTypeDescription
<none>uint256field element in Fq

hashToCurve

Hash a sequence of bytes to a group element in BN254.G_1. We use the hash-and-pray algorithm for now. Rust implementation can be found at https://github.com/EspressoSystems/jellyfish/blob/e1e683c287f20160738e6e737295dd8f9e70577a/primitives/src/signatures/bls_over_bn254.rs#L318

function hashToCurve(bytes memory input) internal view returns (BN254.G1Point memory);

Parameters

NameTypeDescription
inputbytesmessage to be hashed

Returns

NameTypeDescription
<none>BN254.G1Pointgroup element in G_1

verifyBlsSig

Verify a bls signature. Reverts if the signature is invalid

function verifyBlsSig(bytes memory message, BN254.G1Point memory sig, BN254.G2Point memory pk)
    internal
    view;

Parameters

NameTypeDescription
messagebytesmessage to check the signature against
sigBN254.G1Pointsignature represented as a point in BN254.G_1
pkBN254.G2Pointpublic key represented as a point in BN254.G_2

Errors

BLSSigVerificationFailed

error BLSSigVerificationFailed();

ERC1967Proxy

Git Source

Inherits: Proxy

This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn’t conflict with the storage layout of the implementation behind the proxy.

Functions

constructor

Initializes the upgradeable proxy with an initial implementation specified by implementation. If _data is nonempty, it’s used as data in a delegate call to implementation. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements:

  • If data is empty, msg.value must be zero.
constructor(address implementation, bytes memory _data) payable;

_implementation

Returns the current implementation address. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[eth_getStorageAt] RPC call. 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc

function _implementation() internal view virtual override returns (address);

EdOnBN254

Git Source

Edward curve on BN254. This library only implements a serialization function that is consistent with Arkworks’ format. It does not support any group operations.

State Variables

P_MOD

uint256 public constant P_MOD =
    21888242871839275222246405745257275088548364400416034343698204186575808495617

Functions

isYNegative

Check if y-coordinate of G1 point is negative.

function isYNegative(EdOnBN254Point memory point) internal pure returns (bool);

isEqual

Check if two points are equal

function isEqual(EdOnBN254Point memory a, EdOnBN254Point memory b)
    internal
    pure
    returns (bool);

Structs

EdOnBN254Point

struct EdOnBN254Point {
    uint256 x;
    uint256 y;
}

LightClientStateUpdateVK

Git Source

Functions

getVk

function getVk() internal pure returns (IPlonkVerifier.VerifyingKey memory vk);

LightClientStateUpdateVKV2

Git Source

Functions

getVk

function getVk() internal pure returns (IPlonkVerifier.VerifyingKey memory vk);

LightClientStateUpdateVKV3

Git Source

Functions

getVk

function getVk() internal pure returns (IPlonkVerifier.VerifyingKey memory vk);

PlonkVerifier

Git Source

The TurboPlonk formula is: qo * wo = pub_input + q_c + q_mul0 * w0 * w1 + q_mul1 * w2 * w3 + q_lc0 * w0 + q_lc1 * w1 + q_lc2 * w2 + q_lc3 * w3 + q_hash0 * w0 + q_hash1 * w1 + q_hash2 * w2 + q_hash3 * w3 + q_ecc * w0 * w1 * w2 * w3 * wo

State Variables

COSET_K1

uint256 internal constant COSET_K1 =
    0x2f8dd1f1a7583c42c4e12a44e110404c73ca6c94813f85835da4fb7bb1301d4a

COSET_K2

uint256 internal constant COSET_K2 =
    0x1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025

COSET_K3

uint256 internal constant COSET_K3 =
    0x2042a587a90c187b0a087c03e29c968b950b1db26d5c82d666905a6895790c0a

COSET_K4

uint256 internal constant COSET_K4 =
    0x2e2b91456103698adf57b799969dea1c8f739da5d8d40dd3eb9222db7c81e881

BETA_H_X0

uint256 internal constant BETA_H_X0 =
    0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1

BETA_H_X1

uint256 internal constant BETA_H_X1 =
    0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0

BETA_H_Y0

uint256 internal constant BETA_H_Y0 =
    0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4

BETA_H_Y1

uint256 internal constant BETA_H_Y1 =
    0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55

NUM_WIRE_TYPES

The number of wire types of the circuit, TurboPlonk has 5.

uint256 internal constant NUM_WIRE_TYPES = 5

Functions

verify

Verify a single TurboPlonk proofs.

function verify(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    uint256[7] memory publicInput,
    IPlonkVerifier.PlonkProof memory proof
) external view returns (bool);

Parameters

NameTypeDescription
verifyingKeyIPlonkVerifier.VerifyingKeyThe Plonk verification key
publicInputuint256[7]The public input fields
proofIPlonkVerifier.PlonkProofThe TurboPlonk proof

Returns

NameTypeDescription
<none>bool_ A boolean indicating successful verification, false otherwise

_validateProof

Validate all group points and scalar fields. Revert if any are invalid.

function _validateProof(IPlonkVerifier.PlonkProof memory proof) internal pure;

Parameters

NameTypeDescription
proofIPlonkVerifier.PlonkProofA Plonk proof

_verify

function _verify(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    uint256[7] memory publicInput,
    IPlonkVerifier.PlonkProof memory proof
) private view returns (bool);

_computeChallenges

function _computeChallenges(
    IPlonkVerifier.VerifyingKey memory vk,
    uint256[7] memory pi,
    IPlonkVerifier.PlonkProof memory proof
) internal pure returns (Challenges memory res);

_computeLinPolyConstantTerm

Compute the constant term of the linearization polynomial.

r_plonk = PI - L1(x) * alpha^2 - alpha * \prod_i=1..m-1 (w_i + beta * sigma_i + gamma) *
(w_m + gamma) * z(xw)

where m is the number of wire types.

function _computeLinPolyConstantTerm(
    Challenges memory chal,
    IPlonkVerifier.PlonkProof memory proof,
    Poly.EvalData memory evalData
) internal pure returns (uint256 res);

_preparePolyCommitments

function _preparePolyCommitments(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    Challenges memory chal,
    Poly.EvalData memory evalData,
    IPlonkVerifier.PlonkProof memory proof
) internal view returns (BN254.G1Point memory e1, BN254.G1Point memory f1);

Returns

NameTypeDescription
e1BN254.G1PointThe [E]1 in Sec 8.4, step 11 of Plonk
f1BN254.G1PointThe [F]1 in Sec 8.4, step 10 of Plonk

_linearizationPolyComm

Compute the linearization poly commitment

function _linearizationPolyComm(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    Challenges memory challenge,
    Poly.EvalData memory evalData,
    IPlonkVerifier.PlonkProof memory proof
) private view returns (BN254.G1Point memory d1);

Parameters

NameTypeDescription
verifyingKeyIPlonkVerifier.VerifyingKeyThe verifying key
challengeChallengesA set of challenges
evalDataPoly.EvalDataPolynomial evaluation data
proofIPlonkVerifier.PlonkProofA Plonk proof

Returns

NameTypeDescription
d1BN254.G1PointThe [D]1 in Step 9 of Plonk

Errors

InvalidPlonkArgs

Plonk: invalid inputs, either mismatching lengths among input arguments or empty input.

error InvalidPlonkArgs();

WrongPlonkVK

Plonk: wrong verification key used.

error WrongPlonkVK();

Structs

Challenges

Plonk IOP verifier challenges.

struct Challenges {
    uint256 alpha; // 0x00
    uint256 alpha2; // 0x20
    uint256 alpha3; // 0x40
    uint256 beta; // 0x60
    uint256 gamma; // 0x80
    uint256 zeta; // 0xA0
    uint256 v; // 0xC0
    uint256 u; // 0xE0
}

PlonkVerifierV2

Git Source

The TurboPlonk formula is: qo * wo = pub_input + q_c + q_mul0 * w0 * w1 + q_mul1 * w2 * w3 + q_lc0 * w0 + q_lc1 * w1 + q_lc2 * w2 + q_lc3 * w3 + q_hash0 * w0 + q_hash1 * w1 + q_hash2 * w2 + q_hash3 * w3 + q_ecc * w0 * w1 * w2 * w3 * wo

State Variables

COSET_K1

uint256 public constant COSET_K1 =
    0x2f8dd1f1a7583c42c4e12a44e110404c73ca6c94813f85835da4fb7bb1301d4a

COSET_K2

uint256 public constant COSET_K2 =
    0x1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025

COSET_K3

uint256 public constant COSET_K3 =
    0x2042a587a90c187b0a087c03e29c968b950b1db26d5c82d666905a6895790c0a

COSET_K4

uint256 public constant COSET_K4 =
    0x2e2b91456103698adf57b799969dea1c8f739da5d8d40dd3eb9222db7c81e881

BETA_H_X0

uint256 public constant BETA_H_X0 =
    0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1

BETA_H_X1

uint256 public constant BETA_H_X1 =
    0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0

BETA_H_Y0

uint256 public constant BETA_H_Y0 =
    0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4

BETA_H_Y1

uint256 public constant BETA_H_Y1 =
    0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55

NUM_WIRE_TYPES

The number of wire types of the circuit, TurboPlonk has 5.

uint256 internal constant NUM_WIRE_TYPES = 5

Functions

verify

Verify a single TurboPlonk proofs.

function verify(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    uint256[11] memory publicInput,
    IPlonkVerifier.PlonkProof memory proof
) external view returns (bool);

Parameters

NameTypeDescription
verifyingKeyIPlonkVerifier.VerifyingKeyThe Plonk verification key
publicInputuint256[11]The public input fields
proofIPlonkVerifier.PlonkProofThe TurboPlonk proof

Returns

NameTypeDescription
<none>bool_ A boolean indicating successful verification, false otherwise

_validateProof

Validate all group points and scalar fields. Revert if any are invalid.

function _validateProof(IPlonkVerifier.PlonkProof memory proof) internal pure;

Parameters

NameTypeDescription
proofIPlonkVerifier.PlonkProofA Plonk proof

_verify

function _verify(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    uint256[11] memory publicInput,
    IPlonkVerifier.PlonkProof memory proof
) private view returns (bool);

_computeChallenges

function _computeChallenges(
    IPlonkVerifier.VerifyingKey memory vk,
    uint256[11] memory pi,
    IPlonkVerifier.PlonkProof memory proof
) internal pure returns (Challenges memory res);

_computeLinPolyConstantTerm

Compute the constant term of the linearization polynomial.

r_plonk = PI - L1(x) * alpha^2 - alpha * \prod_i=1..m-1 (w_i + beta * sigma_i + gamma) *
(w_m + gamma) * z(xw)

where m is the number of wire types.

function _computeLinPolyConstantTerm(
    Challenges memory chal,
    IPlonkVerifier.PlonkProof memory proof,
    Poly.EvalData memory evalData
) internal pure returns (uint256 res);

_preparePolyCommitments

function _preparePolyCommitments(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    Challenges memory chal,
    Poly.EvalData memory evalData,
    IPlonkVerifier.PlonkProof memory proof
) internal view returns (BN254.G1Point memory e1, BN254.G1Point memory f1);

Returns

NameTypeDescription
e1BN254.G1PointThe [E]1 in Sec 8.4, step 11 of Plonk
f1BN254.G1PointThe [F]1 in Sec 8.4, step 10 of Plonk

_linearizationPolyComm

Compute the linearization poly commitment

function _linearizationPolyComm(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    Challenges memory challenge,
    Poly.EvalData memory evalData,
    IPlonkVerifier.PlonkProof memory proof
) private view returns (BN254.G1Point memory d1);

Parameters

NameTypeDescription
verifyingKeyIPlonkVerifier.VerifyingKeyThe verifying key
challengeChallengesA set of challenges
evalDataPoly.EvalDataPolynomial evaluation data
proofIPlonkVerifier.PlonkProofA Plonk proof

Returns

NameTypeDescription
d1BN254.G1PointThe [D]1 in Step 9 of Plonk

Errors

InvalidPlonkArgs

Plonk: invalid inputs, either mismatching lengths among input arguments or empty input.

error InvalidPlonkArgs();

WrongPlonkVK

Plonk: wrong verification key used.

error WrongPlonkVK();

Structs

Challenges

Plonk IOP verifier challenges.

struct Challenges {
    uint256 alpha; // 0x00
    uint256 alpha2; // 0x20
    uint256 alpha3; // 0x40
    uint256 beta; // 0x60
    uint256 gamma; // 0x80
    uint256 zeta; // 0xA0
    uint256 v; // 0xC0
    uint256 u; // 0xE0
}

PlonkVerifierV3

Git Source

The TurboPlonk formula is: qo * wo = pub_input + q_c + q_mul0 * w0 * w1 + q_mul1 * w2 * w3 + q_lc0 * w0 + q_lc1 * w1 + q_lc2 * w2 + q_lc3 * w3 + q_hash0 * w0 + q_hash1 * w1 + q_hash2 * w2 + q_hash3 * w3 + q_ecc * w0 * w1 * w2 * w3 * wo

State Variables

COSET_K1

uint256 public constant COSET_K1 =
    0x2f8dd1f1a7583c42c4e12a44e110404c73ca6c94813f85835da4fb7bb1301d4a

COSET_K2

uint256 public constant COSET_K2 =
    0x1ee678a0470a75a6eaa8fe837060498ba828a3703b311d0f77f010424afeb025

COSET_K3

uint256 public constant COSET_K3 =
    0x2042a587a90c187b0a087c03e29c968b950b1db26d5c82d666905a6895790c0a

COSET_K4

uint256 public constant COSET_K4 =
    0x2e2b91456103698adf57b799969dea1c8f739da5d8d40dd3eb9222db7c81e881

BETA_H_X0

uint256 public constant BETA_H_X0 =
    0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1

BETA_H_X1

uint256 public constant BETA_H_X1 =
    0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0

BETA_H_Y0

uint256 public constant BETA_H_Y0 =
    0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4

BETA_H_Y1

uint256 public constant BETA_H_Y1 =
    0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55

NUM_WIRE_TYPES

The number of wire types of the circuit, TurboPlonk has 5.

uint256 internal constant NUM_WIRE_TYPES = 5

Functions

verify

Verify a single TurboPlonk proofs.

function verify(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    uint256[5] memory publicInput,
    IPlonkVerifier.PlonkProof memory proof
) external view returns (bool);

Parameters

NameTypeDescription
verifyingKeyIPlonkVerifier.VerifyingKeyThe Plonk verification key
publicInputuint256[5]The public input fields
proofIPlonkVerifier.PlonkProofThe TurboPlonk proof

Returns

NameTypeDescription
<none>bool_ A boolean indicating successful verification, false otherwise

_validateProof

Validate all group points and scalar fields. Revert if any are invalid.

function _validateProof(IPlonkVerifier.PlonkProof memory proof) internal pure;

Parameters

NameTypeDescription
proofIPlonkVerifier.PlonkProofA Plonk proof

_verify

function _verify(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    uint256[5] memory publicInput,
    IPlonkVerifier.PlonkProof memory proof
) private view returns (bool);

_computeChallenges

function _computeChallenges(
    IPlonkVerifier.VerifyingKey memory vk,
    uint256[5] memory pi,
    IPlonkVerifier.PlonkProof memory proof
) internal pure returns (Challenges memory res);

_computeLinPolyConstantTerm

Compute the constant term of the linearization polynomial.

r_plonk = PI - L1(x) * alpha^2 - alpha * \prod_i=1..m-1 (w_i + beta * sigma_i + gamma) *
(w_m + gamma) * z(xw)

where m is the number of wire types.

function _computeLinPolyConstantTerm(
    Challenges memory chal,
    IPlonkVerifier.PlonkProof memory proof,
    Poly.EvalData memory evalData
) internal pure returns (uint256 res);

_preparePolyCommitments

function _preparePolyCommitments(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    Challenges memory chal,
    Poly.EvalData memory evalData,
    IPlonkVerifier.PlonkProof memory proof
) internal view returns (BN254.G1Point memory e1, BN254.G1Point memory f1);

Returns

NameTypeDescription
e1BN254.G1PointThe [E]1 in Sec 8.4, step 11 of Plonk
f1BN254.G1PointThe [F]1 in Sec 8.4, step 10 of Plonk

_linearizationPolyComm

Compute the linearization poly commitment

function _linearizationPolyComm(
    IPlonkVerifier.VerifyingKey memory verifyingKey,
    Challenges memory challenge,
    Poly.EvalData memory evalData,
    IPlonkVerifier.PlonkProof memory proof
) private view returns (BN254.G1Point memory d1);

Parameters

NameTypeDescription
verifyingKeyIPlonkVerifier.VerifyingKeyThe verifying key
challengeChallengesA set of challenges
evalDataPoly.EvalDataPolynomial evaluation data
proofIPlonkVerifier.PlonkProofA Plonk proof

Returns

NameTypeDescription
d1BN254.G1PointThe [D]1 in Step 9 of Plonk

Errors

InvalidPlonkArgs

Plonk: invalid inputs, either mismatching lengths among input arguments or empty input.

error InvalidPlonkArgs();

WrongPlonkVK

Plonk: wrong verification key used.

error WrongPlonkVK();

Structs

Challenges

Plonk IOP verifier challenges.

struct Challenges {
    uint256 alpha; // 0x00
    uint256 alpha2; // 0x20
    uint256 alpha3; // 0x40
    uint256 beta; // 0x60
    uint256 gamma; // 0x80
    uint256 zeta; // 0xA0
    uint256 v; // 0xC0
    uint256 u; // 0xE0
}

PolynomialEval

Git Source

Functions

newEvalDomain

Create a new Radix2EvalDomain with domainSize which should be power of 2.

Will revert if domainSize is not among {2^5, 2^16, 2^20}

The hardcoded values are generated by the rust script eval-domain.

function newEvalDomain(uint256 domainSize) internal pure returns (EvalDomain memory);

evaluateVanishingPoly

function evaluateVanishingPoly(EvalDomain memory self, uint256 zeta)
    internal
    pure
    returns (uint256 res);

evaluateLagrangeOne

Evaluate the lagrange polynomial at point zeta given the vanishing polynomial evaluation vanish_eval.

function evaluateLagrangeOne(
    EvalDomain memory self,
    BN254.ScalarField zeta,
    BN254.ScalarField vanishEval
) internal view returns (BN254.ScalarField res);

evaluatePiPoly

Evaluate public input polynomial at point zeta.

function evaluatePiPoly(
    EvalDomain memory self,
    uint256[7] memory pi,
    uint256 zeta,
    uint256 vanishingPolyEval
) internal view returns (uint256 res);

evalDataGen

compute the EvalData for a given domain and a challenge zeta

function evalDataGen(EvalDomain memory self, uint256 zeta, uint256[7] memory publicInput)
    internal
    view
    returns (EvalData memory evalData);

Errors

UnsupportedDegree

Unsupported polynomial degree, currently size must in 2^{14~17}.

error UnsupportedDegree();

Structs

EvalDomain

a Radix 2 Evaluation Domain

struct EvalDomain {
    uint256 logSize; // log_2(self.size)
    uint256 sizeInv; // Inverse of the size in the field
    uint256[7] elements; // 1, g, g^2, ..., g^6
}

EvalData

stores vanishing poly, lagrange at 1, and Public input poly

struct EvalData {
    BN254.ScalarField vanishEval;
    BN254.ScalarField lagrangeOne;
    BN254.ScalarField piEval;
}

PolynomialEvalV2

Git Source

Functions

newEvalDomain

Create a new Radix2EvalDomain with domainSize which should be power of 2.

Will revert if domainSize is not among {2^5, 2^16, 2^20}

The hardcoded values are generated by the rust script eval-domain.

function newEvalDomain(uint256 domainSize) internal pure returns (EvalDomain memory);

evaluateVanishingPoly

function evaluateVanishingPoly(EvalDomain memory domain, uint256 zeta)
    internal
    pure
    returns (uint256 res);

evaluateLagrangeOne

Evaluate the lagrange polynomial at point zeta given the vanishing polynomial evaluation vanish_eval.

function evaluateLagrangeOne(
    EvalDomain memory domain,
    BN254.ScalarField zeta,
    BN254.ScalarField vanishEval
) internal view returns (BN254.ScalarField res);

evaluatePiPoly

Evaluate public input polynomial at point zeta.

function evaluatePiPoly(
    EvalDomain memory domain,
    uint256[11] memory pi,
    uint256 zeta,
    uint256 vanishingPolyEval
) internal view returns (uint256 res);

evalDataGen

compute the EvalData for a given domain and a challenge zeta

function evalDataGen(EvalDomain memory domain, uint256 zeta, uint256[11] memory publicInput)
    internal
    view
    returns (EvalData memory evalData);

Errors

UnsupportedDegree

Unsupported polynomial degree, currently size must in 2^{14~17}.

error UnsupportedDegree();

Structs

EvalDomain

a Radix 2 Evaluation Domain

struct EvalDomain {
    uint256 logSize; // log_2(domain.size)
    uint256 sizeInv; // Inverse of the size in the field
    uint256[11] elements; // 1, g, g^2, ..., g^10
}

EvalData

stores vanishing poly, lagrange at 1, and Public input poly

struct EvalData {
    BN254.ScalarField vanishEval;
    BN254.ScalarField lagrangeOne;
    BN254.ScalarField piEval;
}

PolynomialEvalV3

Git Source

Functions

newEvalDomain

Create a new Radix2EvalDomain with domainSize which should be power of 2.

Will revert if domainSize is not among {2^5, 2^16, 2^20}

The hardcoded values are generated by the rust script eval-domain.

function newEvalDomain(uint256 domainSize) internal pure returns (EvalDomain memory);

evaluateVanishingPoly

function evaluateVanishingPoly(EvalDomain memory domain, uint256 zeta)
    internal
    pure
    returns (uint256 res);

evaluateLagrangeOne

Evaluate the lagrange polynomial at point zeta given the vanishing polynomial evaluation vanish_eval.

function evaluateLagrangeOne(
    EvalDomain memory domain,
    BN254.ScalarField zeta,
    BN254.ScalarField vanishEval
) internal view returns (BN254.ScalarField res);

evaluatePiPoly

Evaluate public input polynomial at point zeta.

function evaluatePiPoly(
    EvalDomain memory domain,
    uint256[5] memory pi,
    uint256 zeta,
    uint256 vanishingPolyEval
) internal view returns (uint256 res);

evalDataGen

compute the EvalData for a given domain and a challenge zeta

function evalDataGen(EvalDomain memory domain, uint256 zeta, uint256[5] memory publicInput)
    internal
    view
    returns (EvalData memory evalData);

Errors

UnsupportedDegree

Unsupported polynomial degree, currently size must in 2^{14~17}.

error UnsupportedDegree();

Structs

EvalDomain

a Radix 2 Evaluation Domain

struct EvalDomain {
    uint256 logSize; // log_2(domain.size)
    uint256 sizeInv; // Inverse of the size in the field
    uint256[5] elements; // 1, g, g^2, g^3, g^4
}

EvalData

stores vanishing poly, lagrange at 1, and Public input poly

struct EvalData {
    BN254.ScalarField vanishEval;
    BN254.ScalarField lagrangeOne;
    BN254.ScalarField piEval;
}

RewardMerkleTreeVerifier

Git Source

Title: RewardMerkleTreeVerifier

Solidity verifier for RewardMerkleTreeV2 compatible with Espresso’s reward system

  • Arity: 2 (binary tree)
  • Depth: 160 levels
  • Key length: 20 bytes (160 bits) - Ethereum addresses
  • EVM native keccak hash
  • Double hashing of leaves as cheap domain separator

State Variables

TREE_DEPTH

uint256 public constant TREE_DEPTH = 160

Functions

_hashLeaf

function _hashLeaf(uint256 value) internal pure returns (bytes32);

_hashInternal

function _hashInternal(bytes32 left, bytes32 right) internal pure returns (bytes32 hash);

computeRoot

Compute reward commitment from a key-value pair and proof.

Designed to authenticate non-zero values for non-zero keys; caller must ensure neither key nor value is zero.

function computeRoot(address key, uint256 value, bytes32[TREE_DEPTH] memory proof)
    internal
    pure
    returns (bytes32);

Parameters

NameTypeDescription
keyaddressThe key to prove - Ethereum address
valueuint256The value to prove - lifetime earned rewards amount
proofbytes32[TREE_DEPTH]The membership proof containing sibling hashes and numLeaves

Returns

NameTypeDescription
<none>bytes32The computed reward commitment

EspToken

Git Source

Inherits: Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSUpgradeable

Title: EspToken

ERC20 token for the Espresso network, upgradeable via UUPS.

Upgradeability & storage layout (frozen-inheritance pattern) We intentionally do not use __gap slots. Once a version is deployed, its storage layout is frozen and never modified. New state variables are added only in a new child contract (V2, V3, …) that inherits from the previous version and appends fields at the end. This preserves slot order across upgrades without relying on gaps. (Note: upstream OZ parents may include their own gaps—those remain untouched.)

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

This contract is called by the proxy when you deploy this contract

function initialize(
    address owner,
    address initialRecipient,
    uint256 initialSupply,
    string memory name,
    string memory symbol
) public initializer;

_authorizeUpgrade

only the owner can authorize an upgrade

function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner;

renounceOwnership

Cannot renounce ownership

Override renounceOwnership() to revert, preventing accidental or malicious ownership renunciation

function renounceOwnership() public virtual override onlyOwner;

getVersion

Use this to get the implementation contract version

function getVersion()
    public
    pure
    virtual
    returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);

Errors

OwnershipCannotBeRenounced

Cannot renounce ownership

error OwnershipCannotBeRenounced();

EspTokenV2

Git Source

Inherits: EspToken

Title: EspTokenV2

Upgrades EspToken to allow minting by the RewardClaim contract

Upgradeability & storage layout (frozen-inheritance pattern) We intentionally do not use __gap slots. Once a version is deployed, its storage layout is frozen and never modified. New state variables are added only in a new child contract (V2, V3, …) that inherits from the previous version and appends fields at the end. This preserves slot order across upgrades without relying on gaps. (Note: upstream OZ parents may include their own gaps—those remain untouched.)

State Variables

rewardClaim

Address of the RewardClaim contract authorized to mint tokens

Can only be set once, during initialization.

address public rewardClaim

Functions

constructor

constructor() ;

initializeV2

Initializes the V2 upgrade with the RewardClaim contract address

function initializeV2(address _rewardClaim) public onlyOwner reinitializer(2);

Parameters

NameTypeDescription
_rewardClaimaddressAddress of the RewardClaim contract

mint

Mints new tokens to a specified address

Only the RewardClaim contract can mint new tokens

function mint(address to, uint256 amount) public;

Parameters

NameTypeDescription
toaddressAddress to receive the minted tokens
amountuint256Number of tokens to mint

getVersion

Returns the contract version

function getVersion()
    public
    pure
    virtual
    override
    returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);

Returns

NameTypeDescription
majorVersionuint8Major version number
minorVersionuint8Minor version number
patchVersionuint8Patch version number

Errors

OnlyRewardClaim

A non-RewardClaim address attempts to mint

error OnlyRewardClaim();

ZeroRewardClaimAddress

RewardClaim address cannot be zero

error ZeroRewardClaimAddress();

FeeContract

Git Source

Inherits: Initializable, OwnableUpgradeable, UUPSUpgradeable

State Variables

maxDepositAmount

max amount allowed to be deposited to prevent fat finger errors

uint256 public maxDepositAmount

minDepositAmount

uint256 public minDepositAmount

balances

store user balances in a mapping

mapping(address user => uint256 amount) public balances

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

This contract is called by the proxy when you deploy this contract

function initialize(address multisig) public initializer;

fallback

Revert if a method name does not exist

fallback() external payable;

receive

Revert if no method name was called

receive() external payable;

deposit

Allows anyone to deposit an ETH balance for any user

the deposit amount is less than a specified threshold to prevent fat finger errors

function deposit(address user) public payable;

_authorizeUpgrade

only the owner can authorize an upgrade

function _authorizeUpgrade(address newImplementation) internal override onlyOwner;

renounceOwnership

Cannot renounce ownership

Override renounceOwnership() to revert, preventing accidental or malicious ownership renunciation

function renounceOwnership() public virtual override onlyOwner;

getVersion

Use this to get the implementation contract version

function getVersion()
    public
    pure
    returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);

Events

Deposit

Notify a new deposit

event Deposit(address indexed user, uint256 amount);

Log

event Log(string func, uint256 gas);

Upgrade

upgrade event when the proxy updates the implementation it’s pointing to

event Upgrade(address implementation);

Errors

InvalidUserAddress

error types

error InvalidUserAddress();

DepositTooLarge

error DepositTooLarge();

DepositTooSmall

error DepositTooSmall();

FunctionDoesNotExist

error FunctionDoesNotExist();

NoFunctionCalled

error NoFunctionCalled();

OwnershipCannotBeRenounced

error OwnershipCannotBeRenounced();

InitializedAt

Git Source

Inherits: Initializable

State Variables

initializedAtBlock

uint256 public initializedAtBlock

Functions

constructor

constructor() ;

initializeAtBlock

function initializeAtBlock() internal initializer;

LightClient

Git Source

Inherits: Initializable, OwnableUpgradeable, UUPSUpgradeable

Title: Light Client Contract

This contract serves as an always-on client that verifies HotShot’s state (Espresso’s consensus state) which can be used by Rollup contracts on L1 (Ethereum). This state is submitted by any state-prover with evidence which is a SNARK proof that proves consensus. This contract also keeps track of the current epoch. For this version, the epoch is not used.
The light client state primarily consists of:

  • the merkle root of finalized block commitments,
  • the fee ledger commitment and
  • the active stake table commitment

You can use this contract to keep track of its finalized states in safe, authenticated ways.

State Variables

genesisStakeTableState

genesis stake commitment

StakeTableState public genesisStakeTableState

genesisState

genesis block commitment

LightClientState public genesisState

finalizedState

Finalized HotShot’s light client state

LightClientState public finalizedState

permissionedProver

the address of the prover that can call the newFinalizedState function when the contract is in permissioned prover mode. This address is address(0) when the contract is not in permissioned prover mode

address public permissionedProver

stateHistoryRetentionPeriod

Max number of seconds worth of state commitments to record based on this block timestamp

uint32 public stateHistoryRetentionPeriod

stateHistoryFirstIndex

index of first block in block state series

use this instead of index 0 since old states would be set to zero to keep storage costs constant to stateHistoryRetentionPeriod

uint64 public stateHistoryFirstIndex

stateHistoryCommitments

an array to store the L1 block heights, HotShot Block Heights and their respective state history commitments

StateHistoryCommitment[] public stateHistoryCommitments

Functions

constructor

Constructor disables initializers to prevent the implementation contract from being initialized

This is standard practice for OpenZeppelin upgradeable contracts. Storage is on the proxy contract since it calls this cnotract via delegatecall

Note: oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

This contract is called by the proxy when you deploy this contract

function initialize(
    LightClientState memory _genesis,
    StakeTableState memory _genesisStakeTableState,
    uint32 _stateHistoryRetentionPeriod,
    address owner
) public initializer;

Parameters

NameTypeDescription
_genesisLightClientStateThe initial state of the light client
_genesisStakeTableStateStakeTableState
_stateHistoryRetentionPerioduint32The maximum retention period (in seconds) for the state history. the min retention period allowed is 1 hour and max 365 days
owneraddressThe address of the contract owner

currentBlockNumber

returns the current block number

function currentBlockNumber() public view virtual returns (uint256);

getVersion

Use this to get the implementation contract version

function getVersion()
    public
    pure
    virtual
    returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);

Returns

NameTypeDescription
majorVersionuint8The major version of the contract
minorVersionuint8The minor version of the contract
patchVersionuint8The patch version of the contract

_authorizeUpgrade

only the owner can authorize an upgrade

function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner;

renounceOwnership

Cannot renounce ownership

Override renounceOwnership() to revert, preventing accidental or malicious ownership renunciation

function renounceOwnership() public virtual override onlyOwner;

_initializeState

Initialization of contract variables happens in this method because the LightClient contract is upgradable and thus has its constructor method disabled.

function _initializeState(
    LightClientState memory _genesis,
    StakeTableState memory _genesisStakeTableState,
    uint32 _stateHistoryRetentionPeriod
) internal;

Parameters

NameTypeDescription
_genesisLightClientStateThe initial state of the light client
_genesisStakeTableStateStakeTableStateThe initial stake table state of the light client
_stateHistoryRetentionPerioduint32The maximum retention period (in seconds) for the state history. The min retention period allowed is 1 hour and the max is 365 days.

newFinalizedState

Update the latest finalized light client state. It must be updated periodically, especially an update for the last block for every period has to be submitted before any newer state can be accepted since the stake table commitments of that block become the snapshots used for vote verifications later on.

While newState.stakeTable* refers to the (possibly) new stake table states, the entire newState needs to be signed by stakers in finalizedState

if the permissionedProver is set, only the permissionedProver can call this function

the state history for stateHistoryRetentionPeriod L1 blocks are also recorded in the stateHistoryCommitments array

function newFinalizedState(
    LightClientState memory newState,
    IPlonkVerifier.PlonkProof memory proof
) external virtual;

Parameters

NameTypeDescription
newStateLightClientStatenew light client state
proofIPlonkVerifier.PlonkProofPlonkProof

_getVk

a technically unnecessary but luckily zero-cost indirection for the benefit of having IPlonkVerifier.VerifyingKey rust alloy bindings, included only if appear in a public func.

function _getVk() public pure virtual returns (IPlonkVerifier.VerifyingKey memory vk);

verifyProof

Verify the Plonk proof, marked as virtual for easier testing as we can swap VK used in inherited contracts.

function verifyProof(LightClientState memory state, IPlonkVerifier.PlonkProof memory proof)
    internal
    virtual;

setPermissionedProver

set the permissionedProver to the non-zero address provided

this function can also be used to update the permissioned prover once it’s a different address to the current permissioned prover

function setPermissionedProver(address prover) public virtual onlyOwner;

disablePermissionedProverMode

set the permissionedProver to address(0)

if it was already disabled, then revert with the error, NoChangeRequired

function disablePermissionedProverMode() public virtual onlyOwner;

updateStateHistory

Updates the stateHistoryCommitments array when a new finalized state is added and prunes the most outdated element starting from the first element if they fall outside the stateHistoryRetentionPeriod.

the block timestamp is used to determine if the stateHistoryCommitments array should be pruned, based on the stateHistoryRetentionPeriod (seconds).

A FIFO approach is used to remove the most outdated element from the start of the array. However, only one outdated element is removed per invocation of this function, even if multiple elements exceed the retention period. As a result, some outdated elements may remain in the array temporarily until subsequent invocations of this function.

the delete method does not reduce the array length but resets the value at the specified index to zero. the stateHistoryFirstIndex variable acts as an offset to indicate the starting point for reading the array, since the length of the array is not reduced even after deletion.

function updateStateHistory(
    uint64 blockNumber,
    uint64 blockTimestamp,
    LightClientState memory state
) internal;

Parameters

NameTypeDescription
blockNumberuint64The block number of the new finalized state.
blockTimestampuint64The block timestamp used to check the retention period.
stateLightClientStateThe new LightClientState being added to the array.

lagOverEscapeHatchThreshold

checks if the state updates lag behind the specified block threshold based on the provided block number.

Reverts if there isn’t enough state history to make an accurate comparison. Reverts if the blockThreshold is zero

function lagOverEscapeHatchThreshold(uint256 blockNumber, uint256 blockThreshold)
    public
    view
    virtual
    returns (bool);

Parameters

NameTypeDescription
blockNumberuint256The block number to compare against the latest state updates.
blockThresholduint256The number of blocks updates this contract is allowed to lag behind.

Returns

NameTypeDescription
<none>boolbool returns true if the lag exceeds the blockThreshold; otherwise, false.

getHotShotCommitment

get the HotShot commitment that represents the Merkle root containing the leaf at the provided hotShotBlockHeight where the block height in the array is greater than

if the provided hotShotBlockHeight is greater than or equal to the latest commitment in the array, the function reverts.

function getHotShotCommitment(uint256 hotShotBlockHeight)
    public
    view
    virtual
    returns (BN254.ScalarField hotShotBlockCommRoot, uint64 hotshotBlockHeight);

Parameters

NameTypeDescription
hotShotBlockHeightuint256the HotShot block height

Returns

NameTypeDescription
hotShotBlockCommRootBN254.ScalarFieldthe HotShot commitment root
hotshotBlockHeightuint64the HotShot block height for the corresponding commitment root

getStateHistoryCount

get the number of state history commitments

function getStateHistoryCount() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256uint256 The number of state history commitments

setstateHistoryRetentionPeriod

sets the maximum retention period for storing block state history.

Reverts with InvalidMaxStateHistory if the provided value is less than 1 hour, more than 365 days or less than or equal to the current state history retention period.

function setstateHistoryRetentionPeriod(uint32 historySeconds) public onlyOwner;

Parameters

NameTypeDescription
historySecondsuint32The maximum number of seconds for which state history updates will be stored, based on the block timestamp. It must be greater than or equal to the current state history retention period and must be at least 1 hour and max 365 days.

isPermissionedProverEnabled

Check if permissioned prover is enabled

function isPermissionedProverEnabled() public view returns (bool);

Events

Upgrade

upgrade event when the proxy updates the implementation it’s pointing to

event Upgrade(address implementation);

PermissionedProverRequired

when a permissioned prover is set, this event is emitted.

event PermissionedProverRequired(address permissionedProver);

PermissionedProverNotRequired

when the permissioned prover is unset, this event is emitted.

event PermissionedProverNotRequired();

NewState

Event that a new finalized state has been successfully verified and updated

event NewState(
    uint64 indexed viewNum, uint64 indexed blockHeight, BN254.ScalarField blockCommRoot
);

Errors

OutdatedState

The state is outdated and older than currently known finalizedState

error OutdatedState();

InvalidArgs

Invalid user inputs: wrong format or non-sensible arguments

error InvalidArgs();

InvalidProof

Wrong plonk proof or public inputs.

error InvalidProof();

WrongStakeTableUsed

Wrong stake table used, should match finalizedState

error WrongStakeTableUsed();

InvalidAddress

Invalid address

error InvalidAddress();

ProverNotPermissioned

Only a permissioned prover can perform this action

error ProverNotPermissioned();

NoChangeRequired

If the same mode or prover is sent to the function, then no change is required

error NoChangeRequired();

InsufficientSnapshotHistory

Invalid L1 Block for checking Light Client Updates, premature or in the future

error InsufficientSnapshotHistory();

InvalidHotShotBlockForCommitmentCheck

Invalid HotShot Block for checking HotShot commitments, premature or in the future

error InvalidHotShotBlockForCommitmentCheck();

InvalidMaxStateHistory

Invalid Max Block States

error InvalidMaxStateHistory();

OwnershipCannotBeRenounced

Cannot renounce ownership

error OwnershipCannotBeRenounced();

Structs

LightClientState

The finalized HotShot state (as the digest of the entire HotShot state)

struct LightClientState {
    uint64 viewNum;
    uint64 blockHeight;
    BN254.ScalarField blockCommRoot;
}

Properties

NameTypeDescription
viewNumuint64The latest view number of the finalized HotShot chain
blockHeightuint64The block height of the latest finalized block
blockCommRootBN254.ScalarFieldThe merkle root of historical block commitments (BN254::ScalarField)

StakeTableState

The finalized HotShot Stake state (as the digest of the entire HotShot state)

struct StakeTableState {
    uint256 threshold;
    BN254.ScalarField blsKeyComm;
    BN254.ScalarField schnorrKeyComm;
    BN254.ScalarField amountComm;
}

Properties

NameTypeDescription
thresholduint256The (stake-weighted) quorum threshold for a QC to be considered as valid
blsKeyCommBN254.ScalarFieldThe commitment to the BlsVerKey column of the stake table
schnorrKeyCommBN254.ScalarFieldThe commitment to the SchnorrVerKey column of the table
amountCommBN254.ScalarFieldThe commitment to the stake amount column of the stake table

StateHistoryCommitment

Simplified HotShot commitment struct

struct StateHistoryCommitment {
    uint64 l1BlockHeight;
    uint64 l1BlockTimestamp;
    uint64 hotShotBlockHeight;
    BN254.ScalarField hotShotBlockCommRoot;
}

Properties

NameTypeDescription
l1BlockHeightuint64the block height of l1 when this state update was stored
l1BlockTimestampuint64the block timestamp of l1 when this state update was stored
hotShotBlockHeightuint64The block height of the latest finalized HotShot block
hotShotBlockCommRootBN254.ScalarFieldThe merkle root of historical block commitments (BN254::ScalarField)

ArbSys

Git Source

Functions

arbBlockNumber

function arbBlockNumber() external view returns (uint256);

LightClientArbitrum

Git Source

Inherits: LightClient

Functions

currentBlockNumber

function currentBlockNumber() public view virtual override returns (uint256);

ArbSys

Git Source

Functions

arbBlockNumber

function arbBlockNumber() external view returns (uint256);

LightClientArbitrumV2

Git Source

Inherits: LightClientV2

Functions

currentBlockNumber

function currentBlockNumber() public view virtual override returns (uint256);

ArbSys

Git Source

Functions

arbBlockNumber

function arbBlockNumber() external view returns (uint256);

LightClientArbitrumV3

Git Source

Inherits: LightClientV3

Functions

currentBlockNumber

function currentBlockNumber() public view virtual override returns (uint256);

LightClientV2

Git Source

Inherits: LightClient

LightClient V2: with stake table snapshot update during epoch change.

State Variables

blocksPerEpoch

number of blocks per epoch

uint64 public blocksPerEpoch

epochStartBlock

the block height when Epoch-related logic gets activated

uint64 public epochStartBlock

firstEpoch

the first epoch where dynamic stake table is activated, not the numerical value epoch=1

uint64 private firstEpoch

votingStakeTableState

stake table commitments for the current voting stakers

StakeTableState public votingStakeTableState

Functions

initializeV2

Initialize V2

function initializeV2(uint64 _blocksPerEpoch, uint64 _epochStartBlock)
    public
    onlyOwner
    reinitializer(2);

getVersion

function getVersion()
    public
    pure
    virtual
    override
    returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);

newFinalizedState

override the V1’s to disable calling it

function newFinalizedState(LightClientState memory, IPlonkVerifier.PlonkProof memory)
    external
    pure
    override;

setStateHistoryRetentionPeriod

identical as LightClientV1’s setstateHistoryRetentionPeriod() but this function name has the correct camelCase

function setStateHistoryRetentionPeriod(uint32 historySeconds) public virtual onlyOwner;

updateEpochStartBlock

function updateEpochStartBlock(uint64 newEpochStartBlock) public virtual onlyOwner;

newFinalizedState

See detailed doc in LightClient.sol

function newFinalizedState(
    LightClientState memory newState,
    StakeTableState memory nextStakeTable,
    IPlonkVerifier.PlonkProof memory proof
) external virtual;

Parameters

NameTypeDescription
newStateLightClientState
nextStakeTableStakeTableStatethe stake table to use in the next block (same as the current except
proofIPlonkVerifier.PlonkProof

_getVk

function _getVk() public pure virtual override returns (IPlonkVerifier.VerifyingKey memory vk);

verifyProof

compare to V1, we extend public input length from 7 to 11, use a newly generated VK, and enforce correct usage of the nextStakeTable outside the epoch change period.

function verifyProof(
    LightClientState memory state,
    StakeTableState memory nextStakeTable,
    IPlonkVerifier.PlonkProof memory proof
) internal virtual;

currentEpoch

Returns the current epoch according the latest update on finalizedState

function currentEpoch() public view virtual returns (uint64);

Returns

NameTypeDescription
<none>uint64current epoch (computed from the last known hotshot block number)

epochFromBlockNumber

Calculate the epoch number from the hotshot block number

same logic as hotshot_types::utils::epoch_from_block_number()

function epochFromBlockNumber(uint64 _blockNum, uint64 _blocksPerEpoch)
    public
    pure
    virtual
    returns (uint64);

isEpochRoot

Decide if a block height is the an “epoch root” (defined as last block in epoch - 5)

see https://github.com/EspressoSystems/espresso-network/blob/2a904fa17838961cef130d0e87d7b371acaaea42/hotshot-types/src/utils.rs#L475

function isEpochRoot(uint64 blockHeight) public view virtual returns (bool);

isGtEpochRoot

Returns true if the given block number is greater than the epoch root block

function isGtEpochRoot(uint64 blockHeight) public view virtual returns (bool);

Events

NewEpoch

When entering a new epoch and a new stake table snapshot.

event NewEpoch(uint64 epoch);

Errors

MissingEpochRootUpdate

The finalized state for the epoch root of every epoch should NOT be skipped

error MissingEpochRootUpdate();

DeprecatedApi

Invocation on outdated APIs on V1

error DeprecatedApi();

LightClientV3

Git Source

Inherits: LightClientV2

Title: LightClientV3

LightClientV2 with an additional root for gas-efficient state authentication and

improved public input derivation for efficiency and future-proof.

State Variables

authRoot

a state value signed by validators as part of the extended light client state

uint256 public authRoot

_firstEpoch

Unfortunate re-declaration since V2 mark firstEpoch as private

uint64 internal _firstEpoch

Functions

initializeV3

function initializeV3() public onlyOwner reinitializer(3);

getVersion

function getVersion()
    public
    pure
    virtual
    override
    returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);

newFinalizedState

override the V2’s to disable calling it

function newFinalizedState(
    LightClientState memory,
    StakeTableState memory,
    IPlonkVerifier.PlonkProof memory
) external pure override;

newFinalizedState

See detailed doc in LightClient.sol and LightClientV2.sol

more detailed inline code comments, see LightClientV2.sol

diff w/ V2 is marked with “DIFF:” in comment

function newFinalizedState(
    LightClientState memory newState,
    StakeTableState memory nextStakeTable,
    uint256 newAuthRoot,
    IPlonkVerifier.PlonkProof memory proof
) external virtual;

Parameters

NameTypeDescription
newStateLightClientState
nextStakeTableStakeTableState
newAuthRootuint256is the authentication root corresponding to newState
proofIPlonkVerifier.PlonkProof

_getVk

function _getVk() public pure virtual override returns (IPlonkVerifier.VerifyingKey memory vk);

verifyProof

compare to V2, we change public input length from 11 to 5:

4 from votingStakeTableState, 1 from msg_signed := H(authenticated states)

function verifyProof(
    LightClientState memory state,
    StakeTableState memory nextStakeTable,
    uint256 newAuthRoot,
    IPlonkVerifier.PlonkProof memory proof
) internal virtual;

OpsTimelock

Git Source

Inherits: TimelockController

Title: OpsTimelock

A timelock controller for contracts that require faster updates

Timelock used for operational control during early protocol phases. Grants privileged access to core team for upgrades or config changes with a short delay.

Functions

constructor

constructor(
    uint256 minDelay,
    address[] memory proposers,
    address[] memory executors,
    address admin
) TimelockController(minDelay, proposers, executors, admin);

RewardClaim

Git Source

Inherits: IRewardClaim, Initializable, UUPSUpgradeable, PausableUpgradeable, AccessControlUpgradeable, ReentrancyGuardUpgradeable

Title: RewardClaim - Espresso Reward Claim Contract

Allows validators and delegators to claim ESP token rewards based on cryptographic proofs from the Espresso network.

Daily Limit Fairness: This contract enforces daily claim limits on a first-come, first-served basis. Once the limit is reached, remaining claimers must wait until the next day. In unlikely but not impossible scenarios they may be unable to claim for multiple days. The limit (default 1%, max 5% of supply) is set high enough that it should never be reached under normal operation. This is a simple defense-in-depth mechanism to limit potential damage in the unlikely case an attacker is able to circumvent authentication of reward claims. It is not a mechanism to throttle rate of withdrawals under normal operation. Stakers are encouraged to claim their rewards periodically and take advantage of staking their rewards.

Governance Architecture: This contract uses ONLY AccessControlUpgradeable.

  • DEFAULT_ADMIN_ROLE: Can upgrade contract, manage roles, update daily limits
  • PAUSER_ROLE: Can pause/unpause user facing methods in the contract during emergencies Governance: This contract enforces a single-admin model. currentAdmin and DEFAULT_ADMIN_ROLE always reference the same address and can only be changed via grantRole(DEFAULT_ADMIN_ROLE, ...). Any attempt to revoke or renounce the default admin role reverts so that there is always a single admin.

State Variables

espToken

The ESP token contract

EspTokenV2 public espToken

lightClient

The light client contract

LightClientV3 public lightClient

claimedRewards

Tracks total lifetime rewards claimed by each address

mapping(address claimer => uint256 claimed) public claimedRewards

dailyLimitWei

Maximum amount (in Wei) that can be claimed per day across all claimers

Daily limits provide defense-in-depth security: in the unlikely event an exploit for the merkle proof verification is discovered, at most the daily limit can be minted before the contract is paused by the PAUSER_ROLE. This offers a second layer of protection beyond cryptographic verification.

This parameter is intentionally kept non-dynamic such that inflating the token totalSupply will not inflate the value of this limiting parameter.

uint256 public dailyLimitWei

lastSetDailyLimitBasisPoints

Basis points used when daily limit was last set (for reference only)

This is a snapshot of the basis points parameter from the last setDailyLimit call. As total supply changes, this value becomes outdated and no longer represents the actual percentage that dailyLimitWei represents relative to current supply.

uint256 public lastSetDailyLimitBasisPoints

MAX_DAILY_LIMIT_BASIS_POINTS

Maximum daily limit as percentage of total supply in basis points (500 = 5%)

Hardcoded to prevent setting dangerously high limits without a contract upgrade. Increasing this value further would require upgrading the contract, which is intentional to ensure careful consideration and governance of security parameters.

uint256 public constant MAX_DAILY_LIMIT_BASIS_POINTS = 500

BPS_DENOMINATOR

Basis points denominator (100% = 10000 bps)

uint256 public constant BPS_DENOMINATOR = 10000

_currentDay

Current day number (days since epoch)

uint256 private _currentDay

_claimedToday

Amount claimed today across all claimers

No view functions provided for _currentDay or _claimedToday to avoid race conditions. Clients should use call/estimateGas on claimRewards() to check if a claim would succeed. Honest claims should never hit rate limits under normal operation.

It may be potentially useful to add a getter for when the daily limit will reset. We don’t expect to hit the daily limits, therefore implementation in the contract and in clients is not part of the initial release.

uint256 private _claimedToday

PAUSER_ROLE

bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE")

currentAdmin

Current admin address with DEFAULT_ADMIN_ROLE

Tracks the single admin to enforce single-admin invariant

address public currentAdmin

totalClaimed

Total amount of rewards claimed across all users

Enables convenient monitoring of unclaimed rewards by subtracting totalClaimed from total_reward_distributed in the Espresso block header. As long as the total unclaimed rewards is less than the daily limit, honest claims are guaranteed to never exceed the daily limit.

uint256 public totalClaimed

Functions

constructor

constructor() ;

initialize

Initializes the RewardClaim contract

Sets daily limit to 1% of total ESP token supply

function initialize(address _admin, address _espToken, address _lightClient, address _pauser)
    external
    virtual
    initializer;

Parameters

NameTypeDescription
_adminaddressAddress that will be granted DEFAULT_ADMIN_ROLE for contract administration
_espTokenaddressAddress of the ESP token contract
_lightClientaddressAddress of the light client contract
_pauseraddressAddress to be granted the pauser role

pause

function pause() external virtual onlyRole(PAUSER_ROLE);

unpause

function unpause() external virtual onlyRole(PAUSER_ROLE);

setDailyLimit

Updates the daily limit

This function computes an absolute daily limit in Wei by multiplying the supplied basis points with the current total supply of ESP tokens.

nonReentrant protects against reentrancy during the external call to totalSupply.

Unlikely to be exploited: we are calling our token, but the token is upgradable.

DO NOT REMOVE: Added for defense-in-depth.

function setDailyLimit(uint256 basisPoints)
    external
    virtual
    onlyRole(DEFAULT_ADMIN_ROLE)
    nonReentrant;

Parameters

NameTypeDescription
basisPointsuint256Daily limit as basis points of current total supply (1-500 for 0.01%-5%)

claimRewards

Claim all unclaimed staking rewards

nonReentrant is not strictly necessary:

  • claimedRewards updated before external call
  • re-entrancy would change msg.sender making proof verification fail
  • we are calling our token

The token is upgradable, the modifier makes re-entrancy simpler to reason about.

DO NOT REMOVE: added for defense-in-depth and clarity.

See RewardClaim.Reentrancy.Unit.t.sol for regression test.

function claimRewards(uint256 lifetimeRewards, bytes calldata authData)
    external
    virtual
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
lifetimeRewardsuint256Total earned lifetime rewards for the user
authDatabytesAuthentication data from Espresso query service

getVersion

function getVersion()
    external
    pure
    virtual
    returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);

_enforceDailyLimit

See “Daily Limit Fairness” in contract docs.

function _enforceDailyLimit(uint256 amount) internal virtual;

_authorizeUpgrade

only the timelock can authorize an upgrade

function _authorizeUpgrade(address newImplementation)
    internal
    virtual
    override
    onlyRole(DEFAULT_ADMIN_ROLE);

grantRole

Override grantRole to enforce single-admin invariant for DEFAULT_ADMIN_ROLE

When granting DEFAULT_ADMIN_ROLE, automatically revokes it from the current admin. This ensures only one address has DEFAULT_ADMIN_ROLE at any time, atomically. This is intentionally not pausable for emergency governance access.

function grantRole(bytes32 role, address account) public virtual override;

renounceRole

Prevent renouncing DEFAULT_ADMIN_ROLE to preserve governance control

Override renounceRole() to revert when attempting to renounce DEFAULT_ADMIN_ROLE, preventing accidental or malicious admin role renunciation

Revokes role from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked role, emits a {RoleRevoked} event. Requirements:

  • the caller must be callerConfirmation. May emit a {RoleRevoked} event.
function renounceRole(bytes32 role, address callerConfirmation) public virtual override;

revokeRole

Prevent revoking DEFAULT_ADMIN_ROLE to preserve the single-admin invariant.

Revokes role from account. If account had been granted role, emits a {RoleRevoked} event. Requirements:

  • the caller must have role’s admin role. May emit a {RoleRevoked} event.
function revokeRole(bytes32 role, address account) public virtual override;

_verifyAuthRoot

function _verifyAuthRoot(uint256 lifetimeRewards, bytes calldata authData)
    internal
    view
    virtual
    returns (bool);

Events

DailyLimitUpdated

The daily limit is updated

event DailyLimitUpdated(uint256 oldLimit, uint256 newLimit);

Errors

ZeroDailyLimit

Attempting to set daily limit to zero

error ZeroDailyLimit();

DailyLimitTooHigh

Attempting to set daily limit above the maximum allowed percentage

error DailyLimitTooHigh();

NoChangeRequired

Attempting to set daily limit to the current value

error NoChangeRequired();

ZeroTotalSupply

Total ESP token supply is zero during initialization

error ZeroTotalSupply();

ZeroPauserAddress

Pauser address is zero during initialization

error ZeroPauserAddress();

ZeroAdminAddress

Admin address is zero during initialization

error ZeroAdminAddress();

ZeroLightClientAddress

Light client address is zero during initialization

error ZeroLightClientAddress();

ZeroTokenAddress

ESP token address is zero during initialization

error ZeroTokenAddress();

DefaultAdminCannotBeRenounced

Attempted to renounce DEFAULT_ADMIN_ROLE which would break governance

error DefaultAdminCannotBeRenounced();

DefaultAdminCannotBeRevoked

Attempted to revoke DEFAULT_ADMIN_ROLE which would break governance

error DefaultAdminCannotBeRevoked();

SafeExitTimelock

Git Source

Inherits: TimelockController

Title: SafeExitTimelock

A timelock controller for contracts that can have a long delay before updates are applied

The delay on the contract is long enough for users to exit the system if they do not agree with the update

Functions

constructor

constructor(
    uint256 minDelay,
    address[] memory proposers,
    address[] memory executors,
    address admin
) TimelockController(minDelay, proposers, executors, admin);

StakeTable

Git Source

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

NameTypeDescription
_tokenAddressaddressThe address of the staking token
_lightClientAddressaddressThe address of the light client
_exitEscrowPerioduint256The 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

NameTypeDescription
majorVersionuint8The major version of the contract
minorVersionuint8The minor version of the contract
patchVersionuint8The 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

NameTypeDescription
blsVKBN254.G2PointBLS verification key in G2

Returns

NameTypeDescription
<none>bytes32keccak256(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

  1. the validator is already registered
  2. the schnorr key is zero
  3. if the bls signature verification fails (this prevents rogue public-key attacks).
  4. 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

NameTypeDescription
blsVKBN254.G2PointThe BLS verification key
schnorrVKEdOnBN254.EdOnBN254PointThe Schnorr verification key (as the auxiliary info)
blsSigBN254.G1PointThe BLS signature that authenticates the ethereum account this function is called from
commissionuint16in % 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

NameTypeDescription
validatoraddressThe validator to delegate to
amountuint256The amount to delegate

undelegate

Undelegate from a validator

function undelegate(address validator, uint256 amount) public virtual;

Parameters

NameTypeDescription
validatoraddressThe validator to undelegate from
amountuint256The amount to undelegate

claimWithdrawal

Withdraw previously delegated funds after an undelegation.

function claimWithdrawal(address validator) public virtual;

Parameters

NameTypeDescription
validatoraddressThe validator to withdraw from

claimValidatorExit

Withdraw previously delegated funds after a validator has exited

function claimValidatorExit(address validator) public virtual;

Parameters

NameTypeDescription
validatoraddressThe 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

NameTypeDescription
newBlsVKBN254.G2PointThe new BLS verification key
newSchnorrVKEdOnBN254.EdOnBN254PointThe new Schnorr verification key
newBlsSigBN254.G1PointThe 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
}

StakeTableV2

Git Source

Inherits: StakeTable, PausableUpgradeable, AccessControlUpgradeable

Title: Ethereum L1 component of the Espresso Global Confirmation Layer (GCL) stake table.

This contract is an upgrade to the original StakeTable contract. On Espresso mainnet we will only use the V2 contract. On decaf the V2 is used to upgrade the V1 that was first deployed with the original proof of stake release.

The V2 contract contains the following changes:

  1. The functions to register validators and update consensus keys are updated to require both a BLS signature and a Schnorr signature and emit the signatures via events so that the GCL can verify them. The new functions and events have a V2 postfix. After the upgrade components that support registration and key updates must use the V2 functions and listen to the V2 events. The original functions revert with a DeprecatedFunction error in V2.
  2. The exit escrow period can be updated by the owner of the contract within valid bounds (15 blocks to 14 days).
  3. The following functions can be paused by the PAUSER_ROLE:
  • claimWithdrawal(...)
  • claimValidatorExit(...)
  • delegate(...)
  • undelegate(...)
  • deregisterValidator(...)
  • registerValidatorV2(...)
  • updateConsensusKeysV2(...)
  • updateCommission(...)
  • updateMetadataUri(...) When paused, these functions revert with a standard pausable error, EnforcedPause(). Only the PAUSER_ROLE can pause/unpause the contract. Note: updateExitEscrowPeriod is NOT pausable for emergency governance access.
  1. The claimValidatorExit function is overridden to ensure that the validator’s delegatedAmount is updated during this method The update is deferred until the funds are actually withdrawn.
  2. The deregisterValidator function is overridden to ensure that the validator’s delegatedAmount is not updated during this method as it was in v1.
  3. The updateExitEscrowPeriod function is added to allow governance to update the exit escrow period within valid bounds (15 blocks to 14 days).
  4. The pause and unpause functions are added for emergency control.
  5. The commission rate for validators can be updated with the updateCommission function.
  6. The activeStake variable is added to allow governance to track the total stake in the contract. The activeStake is the total stake that is not awaiting exit or in exited state.
  7. Unique undelegation IDs are assigned to each undelegation via an auto-incrementing counter for better event tracking. The undelegationIds public mapping stores IDs alongside the base undelegations mapping. Events UndelegatedV2, WithdrawalClaimed, and ValidatorExitClaimed include the undelegation ID as an indexed parameter for efficient querying and tracking.
  8. Validators must provide a metadata URI during registration and can update it via updateMetadataUri. The metadata URI is event-sourced only (not stored on-chain for gas efficiency). The ValidatorRegisteredV2 event includes the metadata URI, and a new MetadataUriUpdated event is emitted when validators update their URI. Metadata URIs can be empty and cannot exceed 2048 bytes.
  9. A minimum delegation amount (minDelegateAmount) is enforced to prevent dust delegations and reduce state bloat. The minimum is initialized to 1 ESP token (1 ether) in initializeV2 and can be updated by governance via the setMinDelegateAmount function. The delegate function reverts with DelegateAmountTooSmall if the delegation amount is below the minimum.

The StakeTableV2 contract ABI is a superset of the original ABI. Consumers of the contract can use the V2 ABI, even if they would like to maintain backwards compatibility. Governance: This contract enforces a single-admin model. owner() and DEFAULT_ADMIN_ROLE always reference the same address and can only be changed via transferOwnership() (directly or through grantRole(DEFAULT_ADMIN_ROLE, ...), which delegates to the transfer). Any attempt to revoke or renounce the default admin role, or to renounce ownership, reverts. This removes governance drift.

All functions are marked as virtual so that future upgrades can override them.

State Variables

PAUSER_ROLE

bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE")

MAX_METADATA_URI_LENGTH

Maximum length for metadata URIs (in bytes)

uint256 public constant MAX_METADATA_URI_LENGTH = 2048

MAX_COMMISSION_BPS

Maximum commission in basis points (100% = 10000 bps)

uint16 public constant MAX_COMMISSION_BPS = 10000

MIN_EXIT_ESCROW_PERIOD

Minimum exit escrow period (2 days)

This is a technical minimum bound enforced by the contract. Setting the exit escrow period to this minimum does not guarantee safety. The actual exit escrow period must be set such that the contract holds funds long enough until they are no longer staked in Espresso, allowing sufficient time for validators to exit the active validator set and for slashing evidence to be submitted. Governance should set a value appropriate for Espresso network parameters (e.g., blocksPerEpoch, blockTime, and epoch duration) to ensure security.

uint64 public constant MIN_EXIT_ESCROW_PERIOD = 2 days

MAX_EXIT_ESCROW_PERIOD

Maximum exit escrow period (14 days)

Reasonable upper bound to prevent excessive lockup periods

uint64 public constant MAX_EXIT_ESCROW_PERIOD = 14 days

minCommissionIncreaseInterval

Minimum time interval between commission increases (in seconds)

uint256 public minCommissionIncreaseInterval

maxCommissionIncrease

Maximum commission increase allowed per increase (in basis points)

uint16 public maxCommissionIncrease

activeStake

Total stake in active (not marked for exit) validators in the contract

uint256 public activeStake

minDelegateAmount

min delegate amount

uint256 public minDelegateAmount

commissionTracking

Commission tracking for each validator

mapping(address validator => CommissionTracking tracking) public commissionTracking

schnorrKeys

Schnorr keys that have been seen by the contract

ensures a bijective mapping between schnorr key and ethereum account and prevents 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 Schnorr key twice.

mapping(bytes32 schnorrKey => bool used) public schnorrKeys

nextUndelegationId

Auto-incrementing counter for unique undelegation IDs

Initialized to 1 in initializeV2 so that 0 can be used to identify V1 undelegations

uint64 private nextUndelegationId

undelegationIds

Mapping from (validator, delegator) to undelegation ID

Separate from base Undelegation struct since base contract is immutable

mapping(address validator => mapping(address delegator => uint64 id)) private undelegationIds

Functions

constructor

Constructor

This function is overridden to disable initializers

constructor() ;

initializeV2

Reinitialize the contract

initialCommissions must be an empty array if the contract we’re upgrading has not been used before (e.g. on mainnet). On decaf (sepolia), this must be called with the current commissions of pre-existing validators read from L1 events.

Sets up roles and transfers ownership to admin. The deployer picks the admin address (timelock, multisig, etc.) based on config.

function initializeV2(
    address pauser,
    address admin,
    uint256 initialActiveStake,
    InitialCommission[] calldata initialCommissions
) public onlyOwner reinitializer(2);

Parameters

NameTypeDescription
pauseraddressThe address to be granted the pauser role
adminaddressThe address to be granted the default admin role and ownership. This should be a timelock contract address, multisig, or another governance address.
initialActiveStakeuint256The initial active stake in the contract
initialCommissionsInitialCommission[]commissions of validators

getVersion

Get the version of the contract

This function is overridden to return the version of the contract

function getVersion()
    public
    pure
    virtual
    override
    returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion);

pause

Pause the contract

This function is only callable by the PAUSER_ROLE

function pause() external onlyRole(PAUSER_ROLE);

unpause

Unpause the contract

This function is only callable by the PAUSER_ROLE

function unpause() external onlyRole(PAUSER_ROLE);

transferOwnership

Transfers ownership and keeps DEFAULT_ADMIN_ROLE in sync Grants the role to new owner and revokes from old owner. Access control is enforced by both onlyRole(DEFAULT_ADMIN_ROLE) and super.transferOwnership() which requires onlyOwner. This ensures that only the current admin (who holds both ownership and DEFAULT_ADMIN_ROLE) can transfer ownership. This is intentionally not pausable for emergency governance access.

Transfers ownership of the contract to a new account (newOwner). Can only be called by the current owner.

function transferOwnership(address newOwner)
    public
    virtual
    override
    onlyRole(DEFAULT_ADMIN_ROLE);

grantRole

Grants a role. Granting DEFAULT_ADMIN_ROLE transfers ownership first, which handles both role grant and ownership transfer atomically. This is intentionally not pausable for emergency governance access.

Grants role to account. If account had not been already granted role, emits a {RoleGranted} event. Requirements:

  • the caller must have role’s admin role. May emit a {RoleGranted} event.
function grantRole(bytes32 role, address account) public virtual override;

revokeRole

Prevent revoking DEFAULT_ADMIN_ROLE to preserve the single-admin invariant.

Revokes role from account. If account had been granted role, emits a {RoleRevoked} event. Requirements:

  • the caller must have role’s admin role. May emit a {RoleRevoked} event.
function revokeRole(bytes32 role, address account) public virtual override;

renounceRole

Prevent renouncing DEFAULT_ADMIN_ROLE to preserve the single-admin invariant.

Revokes role from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function’s purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked role, emits a {RoleRevoked} event. Requirements:

  • the caller must be callerConfirmation. May emit a {RoleRevoked} event.
function renounceRole(bytes32 role, address callerConfirmation) public virtual override;

claimValidatorExit

Withdraw previously delegated funds after a validator has exited

This function is overridden to deduct the amount from the validator’s delegatedAmount

and to add pausable functionality

since the delegated Amount is no longer updated during validator exit

function claimValidatorExit(address validator) public virtual override whenNotPaused;

Parameters

NameTypeDescription
validatoraddressThe validator to withdraw from

claimWithdrawal

Withdraw previously delegated funds after an undelegation

This function is overridden to add pausable functionality and emit ID in event

function claimWithdrawal(address validator) public virtual override whenNotPaused;

Parameters

NameTypeDescription
validatoraddressThe validator to withdraw from

delegate

Delegate funds to a validator

This function is overridden to add pausable functionality

The function body is copied from V1 to maintain checks-effects-interactions pattern.

function delegate(address validator, uint256 amount) public virtual override whenNotPaused;

Parameters

NameTypeDescription
validatoraddressThe validator to delegate to
amountuint256The amount to delegate

undelegate

Undelegate funds from a validator

This function is overridden to add pausable functionality and emit UndelegatedV2

The undelegation ID can be retrieved from the UndelegatedV2 event or via getUndelegation()

function undelegate(address validator, uint256 amount) public virtual override whenNotPaused;

Parameters

NameTypeDescription
validatoraddressThe validator to undelegate from
amountuint256The amount to undelegate

deregisterValidator

Deregister a validator

This function is overridden to add pausable functionality

and to ensure that the validator’s delegatedAmount is not updated until withdrawal

delegatedAmount represents the no. of tokens that have been delegated to a validator, even if it’s not participating in consensus

emits ValidatorExitV2 instead of ValidatorExit

function deregisterValidator() public virtual override whenNotPaused;

registerValidatorV2

Register a validator in the stake table

This function is overridden to add pausable functionality

and to add schnorrSig validation

function registerValidatorV2(
    BN254.G2Point memory blsVK,
    EdOnBN254.EdOnBN254Point memory schnorrVK,
    BN254.G1Point memory blsSig,
    bytes memory schnorrSig,
    uint16 commission,
    string memory metadataUri
) external virtual whenNotPaused;

Parameters

NameTypeDescription
blsVKBN254.G2PointThe BLS verification key
schnorrVKEdOnBN254.EdOnBN254PointThe Schnorr verification key
blsSigBN254.G1PointThe BLS signature that authenticates the BLS VK
schnorrSigbytesThe Schnorr signature that authenticates the Schnorr VK
commissionuint16in % with 2 decimals, from 0.00% (value 0) to 100% (value 10_000)
metadataUristringThe metadata URI for the validator

updateConsensusKeysV2

Update the consensus keys of a validator

This function is overridden to add pausable functionality

and to add schnorrSig validation

function updateConsensusKeysV2(
    BN254.G2Point memory blsVK,
    EdOnBN254.EdOnBN254Point memory schnorrVK,
    BN254.G1Point memory blsSig,
    bytes memory schnorrSig
) public virtual whenNotPaused;

Parameters

NameTypeDescription
blsVKBN254.G2PointThe new BLS verification key
schnorrVKEdOnBN254.EdOnBN254PointThe new Schnorr verification key
blsSigBN254.G1PointThe BLS signature that authenticates the blsVK
schnorrSigbytesThe Schnorr signature that authenticates the schnorrVK

updateCommission

Update the commission rate for a validator

  1. Only one commission increase per minCommissionIncreaseInterval is allowed.
  2. The commission increase cannot exceed maxCommissionIncrease. These limits protect stakers from sudden large commission increases, particularly by exiting validators.
function updateCommission(uint16 newCommission) external virtual whenNotPaused;

Parameters

NameTypeDescription
newCommissionuint16The new commission rate in % with 2 decimals (0 to 10_000)

updateMetadataUri

Update the metadata URI for a validator

The metadata URI is NOT stored on-chain. Off-chain indexers must listen to the MetadataUriUpdated event to track the current URI. URIs should be kept reasonably short for gas efficiency (max 2048 bytes). Only the validator (msg.sender) can update their own metadata URI.

No format validation is performed on the URI - any string within length limits (including empty string) is accepted. Consumers should validate URI format and accessibility off-chain.

function updateMetadataUri(string memory metadataUri) external virtual whenNotPaused;

Parameters

NameTypeDescription
metadataUristringThe new metadata URI

setMinCommissionUpdateInterval

Set the minimum interval between commission updates

function setMinCommissionUpdateInterval(uint256 newInterval)
    external
    virtual
    onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
newIntervaluint256The new minimum interval in seconds

setMaxCommissionIncrease

Set the maximum commission increase allowed per update

function setMaxCommissionIncrease(uint16 newMaxIncrease)
    external
    virtual
    onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
newMaxIncreaseuint16The new maximum increase in basis points (e.g., 500 = 5%)

_initializeCommissions

Initialize validator commissions during V2 migration

This function is used to retroactively initialize commission storage for validators that were registered before the V2 upgrade. On decaf, this will be called with current commission values read from L1 events. On mainnet, this will be called with an empty array since there are no pre-existing validators.

function _initializeCommissions(InitialCommission[] calldata initialCommissions) private;

Parameters

NameTypeDescription
initialCommissionsInitialCommission[]Array of InitialCommission structs containing validator addresses and their commissions

_initializeActiveStake

Initialize the active stake in the contract

function _initializeActiveStake(uint256 initialActiveStake) private;

Parameters

NameTypeDescription
initialActiveStakeuint256The initial active stake in the contract

validateMetadataUri

Validate metadata URI length

Public view function to allow external validation before transaction submission

function validateMetadataUri(string memory metadataUri) public pure;

Parameters

NameTypeDescription
metadataUristringThe metadata URI to validate

updateExitEscrowPeriod

Update the exit escrow period

This function ensures that the exit escrow period is within the valid range (MIN_EXIT_ESCROW_PERIOD to MAX_EXIT_ESCROW_PERIOD). However, governance MUST set a value that ensures funds are held until they are no longer staked in Espresso, accounting for validator exit time and slashing evidence submission windows. This function is not pausable so that governance can perform emergency updates in the presence of system upgrades.

function updateExitEscrowPeriod(uint64 newExitEscrowPeriod)
    external
    virtual
    onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
newExitEscrowPerioduint64The new exit escrow period

getUndelegation

Get details of an undelegation for a (validator, delegator) pair

function getUndelegation(address validator, address delegator)
    external
    view
    returns (uint64 id, uint256 amount, uint256 unlocksAt);

Parameters

NameTypeDescription
validatoraddressAddress of the validator
delegatoraddressAddress of the delegator

Returns

NameTypeDescription
iduint64Unique ID of the undelegation
amountuint256Amount of tokens undelegated
unlocksAtuint256Timestamp when tokens can be claimed

_hashSchnorrKey

function _hashSchnorrKey(EdOnBN254.EdOnBN254Point memory schnorrVK)
    internal
    pure
    returns (bytes32);

ensureNewKeys

Ensure that the BLS and Schnorr keys are not already used

function ensureNewKeys(BN254.G2Point memory blsVK, EdOnBN254.EdOnBN254Point memory schnorrVK)
    internal
    view;

Parameters

NameTypeDescription
blsVKBN254.G2PointThe BLS verification key
schnorrVKEdOnBN254.EdOnBN254PointThe Schnorr verification key

registerValidator

Deprecate previous registration function

This function is overridden to revert with a DeprecatedFunction error

users must call registerValidatorV2 instead

function registerValidator(
    BN254.G2Point memory,
    EdOnBN254.EdOnBN254Point memory,
    BN254.G1Point memory,
    uint16
) external pure override;

updateConsensusKeys

Deprecate previous updateConsensusKeys function

This function is overridden to revert with a DeprecatedFunction error

users must call updateConsensusKeysV2 instead

function updateConsensusKeys(
    BN254.G2Point memory,
    EdOnBN254.EdOnBN254Point memory,
    BN254.G1Point memory
) external pure override;

setMinDelegateAmount

Set the minimum delegate amount

function setMinDelegateAmount(uint256 newMinDelegateAmount)
    external
    virtual
    onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
newMinDelegateAmountuint256The new minimum delegate amount in wei

_authorizeUpgrade

Authorize an upgrade to a new implementation

This function is overridden to use AccessControl instead of Ownable Only addresses with DEFAULT_ADMIN_ROLE can authorize upgrades

function _authorizeUpgrade(address newImplementation)
    internal
    virtual
    override
    onlyRole(DEFAULT_ADMIN_ROLE);

Parameters

NameTypeDescription
newImplementationaddressThe address of the new implementation

Events

ValidatorRegisteredV2

A validator is registered in the stake table

the blsSig and schnorrSig are validated by the Espresso Network

event ValidatorRegisteredV2(
    address indexed account,
    BN254.G2Point blsVK,
    EdOnBN254.EdOnBN254Point schnorrVK,
    uint16 commission,
    BN254.G1Point blsSig,
    bytes schnorrSig,
    string metadataUri
);

ConsensusKeysUpdatedV2

A validator updates their consensus keys

the blsSig and schnorrSig are validated by the Espresso Network

event ConsensusKeysUpdatedV2(
    address indexed account,
    BN254.G2Point blsVK,
    EdOnBN254.EdOnBN254Point schnorrVK,
    BN254.G1Point blsSig,
    bytes schnorrSig
);

ExitEscrowPeriodUpdated

The exit escrow period is updated

event ExitEscrowPeriodUpdated(uint64 newExitEscrowPeriod);

CommissionUpdated

A validator updates their commission rate

the timestamp is emitted to simplify processing in the GCL

event CommissionUpdated(
    address indexed validator, uint256 timestamp, uint16 oldCommission, uint16 newCommission
);

Parameters

NameTypeDescription
validatoraddressThe address of the validator
timestampuint256The timestamp of the update
oldCommissionuint16
newCommissionuint16The new commission rate

MinCommissionUpdateIntervalUpdated

The minimum commission update interval is updated

event MinCommissionUpdateIntervalUpdated(uint256 newInterval);

Parameters

NameTypeDescription
newIntervaluint256The new minimum update interval in seconds

MaxCommissionIncreaseUpdated

The maximum commission increase is updated

event MaxCommissionIncreaseUpdated(uint16 newMaxIncrease);

Parameters

NameTypeDescription
newMaxIncreaseuint16The new maximum commission increase in basis points

UndelegatedV2

A delegator undelegated funds from a validator (V2 with unlocksAt and undelegationId)

event UndelegatedV2(
    address indexed delegator,
    address indexed validator,
    uint64 indexed undelegationId,
    uint256 amount,
    uint256 unlocksAt
);

Parameters

NameTypeDescription
delegatoraddressThe address of the delegator
validatoraddressThe address of the validator
undelegationIduint64Unique identifier for this undelegation
amountuint256The amount undelegated
unlocksAtuint256The timestamp when the funds can be claimed

WithdrawalClaimed

A delegator claimed an undelegation (V2 with undelegationId)

event WithdrawalClaimed(
    address indexed delegator,
    address indexed validator,
    uint64 indexed undelegationId,
    uint256 amount
);

Parameters

NameTypeDescription
delegatoraddressThe address of the delegator
validatoraddressThe address of the validator
undelegationIduint64Unique identifier for this undelegation
amountuint256The amount claimed

ValidatorExitClaimed

A delegator claimed funds after validator exit

event ValidatorExitClaimed(
    address indexed delegator, address indexed validator, uint256 amount
);

Parameters

NameTypeDescription
delegatoraddressThe address of the delegator
validatoraddressThe address of the validator
amountuint256The amount claimed

ValidatorExitV2

A validator initiated an exit (V2 with unlocksAt)

event ValidatorExitV2(address indexed validator, uint256 unlocksAt);

Parameters

NameTypeDescription
validatoraddressThe address of the validator
unlocksAtuint256The timestamp when delegators can claim their funds

MetadataUriUpdated

A validator updated their metadata URI

event MetadataUriUpdated(address indexed validator, string metadataUri);

Parameters

NameTypeDescription
validatoraddressThe address of the validator
metadataUristringThe new metadata URI

MinDelegateAmountUpdated

The minimum delegate amount is updated

event MinDelegateAmountUpdated(uint256 newMinDelegateAmount);

Parameters

NameTypeDescription
newMinDelegateAmountuint256The new minimum delegate amount in wei

Errors

InvalidSchnorrSig

The Schnorr signature is invalid (either the wrong length or the wrong key)

error InvalidSchnorrSig();

DeprecatedFunction

The function is deprecated as it was replaced by a new function

error DeprecatedFunction();

CommissionUpdateTooSoon

The commission update is too soon after the last update

error CommissionUpdateTooSoon();

CommissionIncreaseExceedsMax

The commission increase exceeds the maximum allowed increase

error CommissionIncreaseExceedsMax();

CommissionUnchanged

The commission value is unchanged

error CommissionUnchanged();

InvalidRateLimitParameters

The rate limit parameters are invalid

error InvalidRateLimitParameters();

CommissionAlreadyInitialized

The validator commission has already been initialized

error CommissionAlreadyInitialized(address validator);

InitialActiveStakeExceedsBalance

The initial active stake exceeds the balance of the contract

error InitialActiveStakeExceedsBalance();

SchnorrKeyAlreadyUsed

The Schnorr key has been previously registered in the contract.

error SchnorrKeyAlreadyUsed();

DefaultAdminCannotBeRevoked

Attempted to revoke DEFAULT_ADMIN_ROLE which would break single-admin governance

error DefaultAdminCannotBeRevoked();

DefaultAdminCannotBeRenounced

Attempted to renounce DEFAULT_ADMIN_ROLE which would break single-admin governance

error DefaultAdminCannotBeRenounced();

NoUndelegationFound

No undelegation exists for the given validator and delegator

error NoUndelegationFound();

InvalidMetadataUriLength

The metadata URI exceeds maximum allowed length

error InvalidMetadataUriLength();

DelegateAmountTooSmall

The delegate amount is too small

error DelegateAmountTooSmall();

MinDelegateAmountTooSmall

The minimum delegate amount is too small

error MinDelegateAmountTooSmall();

Structs

CommissionTracking

Struct for tracking validator commission and last increase time

struct CommissionTracking {
    uint16 commission;
    uint256 lastIncreaseTime;
}

InitialCommission

Struct for initializing validator commissions during migration

struct InitialCommission {
    address validator;
    uint16 commission;
}