Chapter 11
Stake Table Smart Contract

Requirements: Stake Table Contract Requirements


Contents



11.1 Overview
11.2 Transition from static stake table to proof of stake



11.1 # Overview

The Espresso stake table smart contract is an EVM smart contract deployed to Ethereum layer 1 (L1) and it’s purpose is to securely facilitate permissionless staking for the GCL. To that extent it will expose public functions for validator registration and exits, delegation deposit and withdrawals (with an escrow period) of the staking asset (ESP Token), as well as emit EVM events. The GCL can use these EVM events to build a stake table at any finalized Ethereum block height. The GCL only defines a stake table per epoch and handles the mapping of epochs to finalized L1 block number. The contract functions will be called by staking user interfaces.

The participants relevant to the smart contract are the GCL and

Validator

A GCL node that participates in consensus, operated by a GCL node operator.

Delegator

An ESP token holder who would like to stake ESP tokens to participate in securing the GCL. The entitity behind a delegator may also be a validator.

GCL

Staking user interface

A graphical or command line interface staking user interface (UI) that allows validators and delegators to participate in the staking protocol.

Contract Admin

An L1 account (an externally owned account (EOA) or multisig smart contract).

The stake table contract supports the following operations

In addition to that the following methods exist that can only be invoked by the contract admin:

In summary the stake table needs implement the following functionality

In other words the stake table serves as a timestamped (by ethereum block number) ledger for stake table events with some restrictions, notably an escrow period for exiting. The stake table contract does not itself compute a stake table but merely ensures that the flow of funds and respective information satisfy the requirements of validators, delegators and the GCL.

The GCL will receive the following events, and associated data

The BLS key is used as the consensus signing key and the Schnorr key is used to sign GCL state update when building a light client proof. The commission is the percentage of fees (with 2 decimal points) that the validator will earn from delegated funds.

The GCL’s interface with the stake table smart contract is via EVM events. EVM events are emitted when an EVM change (here the L1) executes EVM transactions. By “emitted” we mean that event associated with the transaction in the EVM block and part of the block. Every EVM transaction can have zero or more EVM events associated with it. EVM events can have arbitry data attached to them. EVM events are persistent, in the sense that if the execution of a transaction emitted a certain event we expect that event and its associated data to be forever part of the history of the L1 and obtainable with the eth_getLogs RPC call to an Ethereum JsonRPC node. In practice we do not call the Ethereum JsonRPC directly but use the rust code generated by foundry for this purpose (the “contract bindings”).

If an EVM transaction fails to execute it is said “to revert”. The revert causes the transaction to not make any changes to the state (other than consume gas for the execution until the revert) and to not emit any EVM events. Importantly, if a transaction fails to execute there will be no EVM events emitted in this transaction. When we say the contract prevents something from happening we mean that it causes a transaction that violates this constraint to revert, which means that no events will be emitted.

For the GCL the following information about the behaviour of the stake table contract is of interest

The GCL implementation of the stake table must not assume that stake table smart contract implements all requirements correctly. However, the GCL should not attempt to handle bugs in the smart contract. If the smart contract does not satisfy its requirements the behaviour of the GCL is not always well defined. If for example we receive a registration event for a validator that is already registered this is a serious bug in the smart contract and the GCL can panic.

For certain operations we will trust the smart contract to handle it correctly. For example the GCL will not verify at runtime that tokens were actually transferred to the smart contract. However as part of the requirements for the stake table smart contracts we will implement tests that ensure the smart contract correctly handles the requirements.

The GCL needs to handle the contract events as follows.

The GCL has some flexibility on how go about the implementation but there are some constraints

Assume that the internal stake table represention in memory is as follows in the GCL.

assume that we have a stake table for epoch e. If we are upgrading from the static stake table to PoS the mapping may be empty.

1.
Fetch the block number where the stake table contract was deployed from the contract: initializedAtBlock. The contract will expose such a public method to make it easy to know from what L1 block number to fetch events from.
2.
Assume the Membership trait function add_epoch_root is called with epoch e+1 and header h.
3.
Fetch all stake table events from initializedAtBlock to h.l1_finalized (inclusive).
4.
For each event modify validators as follows

The consensus algorithm and the Membership implementation do not need delegation information. The GCL can implement a way to convert the GCL internal representation of the stake table (which includes delegations and is used for rewards computation in the GCL) to the Membership implementation. Alternatively the GCL could opt for a bigger implementation of the Membership trait that serves also as internal GCL type.

While the algorithm outline above should be correct, we do not want to fetch all stake table events each time add_epoch_root is called because this would be slow and expensive. Therefore as an optimization we should at minimum fetch finalized stake table events in a separate thread. We should use those pre-fetched events when add_epoch_root is called. As a second optimization we should compute the stake table of the new epoch by applying the new events to the stake table of the previous epoch.

11.2 Transition from static stake table to proof of stake

Prior to performing the proof of stake upgrade the following will happen on L1.

The process of initial validator registration and delegation may take some time and we will not carry out the Proof of Stake (POS) upgrade until we are happy with the state of the stake table contract on L1.

When the POS upgrade is activated in the GCL consensus will start calling add_epoch_root to build the stake table from L1 events in the stake table contract. Two epochs later consensus will start using the new stake table for voting but will keep using the existing data availability (DA) stake table.