The roles in Liquid Collective's Ethereum implementation, and staking infrastructure overview.
Key roles in Liquid Collective
The teams building and operating Liquid Collective work together to ensure the smooth functioning of the protocol and provide a seamless and secure Ethereum staking experience. You can learn more about Liquid Collective's approach to working with these roles in our post.
Platforms
Platforms provide a seamless on-ramp and access for users to interact with the Liquid Collective protocol. There are two types of Liquid Collective Platforms. Platforms either enable minting and redemption of LsETH, or enable secondary interactions.
In the Liquid Collective protocol's Platforms are also referred to as Allowlisters, as Platforms that enable minting and redemption currently function as the agents responsible for adding users to the Allowlist.
You can learn more about Liquid Collective Platforms in the .
Wallet and Custody Providers
Wallet Providers and Custody Providers offer LsETH token storage and signing infrastructure. Wallet and Custody Providers enable Platforms to easily access and distribute LsETH to their users through custody and/or embedded minting services. In some cases, these Providers and Platforms are the same entities.
Service Providers
Service Providers provide development, consulting, attestation, legal, or technological services to the Liquid Collective. Liquid Collective seeks to collaborate with existing web3 teams in the development of the protocol’s liquid staking offering.
Examples of Liquid Collective Service Providers include , , , and Hypernative.
Node Operators
Node Operators run the Ethereum validator infrastructure on Liquid Collective, registering validator keys with the protocol, performing validation duties, and earning network rewards for doing so. Liquid Collective does not run validator infrastructure, but instead delegates that critical task to proven Node Operators that meet high performance standards.
You can learn more about Liquid Collective Node Operators in the .
Oracle Operators
Infrastructure providers, operating a daemon app to report Ethereum consensus layer data to the Liquid Collective protocol. This data is necessary so the Liquid Collective protocol can account for the network rewards earned by validators.
Oracles report to Liquid Collective's core contract on the balance of underlying staked tokens plus accrued staking rewards, minus any slashing penalties. This information informs for deposit and withdrawal (when supported, after withdrawals are enabled on Ethereum), alongside supporting DeFi reporting.
Liquid Collective is designed to provide a secure and enterprise-grade liquid staking solution which necessitates sanctions checks on the protocol’s active validator set. Liquid Collective Node Operators must meet certain protocol performance and compliance requirements, and have the capacity to scale to a large number of validator nodes.
Liquid Collective works only with security-focused Node Operators that institute best practices to generate network rewards, including:
To reduce the risk impact of validator operations, and to increase decentralization, Liquid Collective delegates tokens to multiple independent validator Node Operators. The staked tokens are distributed across Node Operators in a round-robin manner so that the Liquid Collective protocol is supported by a broad and dispersed active validator set. As a result, the risk is distributed, which should minimize staked ETH exposure to any one operator.
Node Operators in Liquid Collective's active set also support the protocol's by providing coverage for deductibles, up to a cap, against slashing incidents and missed rewards incurred due to the fault of their infrastructure.
You can find in-depth technical documentation on Liquid Collective's Ethereum validator infrastructure in .
ETH Liquid Staking Documentation
Liquid Collective is a decentralized liquid staking protocol. Multi-chain capable, Liquid Collective launched Ethereum liquid staking first and aims to implement liquid staking for other networks in the future.
This documentation is specific to Liquid Collective's Ethereum liquid staking protocol and its ETH liquid staking token, Liquid Staked ETH (LsETH).
For general Liquid Collective documentation, visit Liquid Collective's core documentation here.
ETH liquid staking with Liquid Collective
Liquid staking enables participants to contribute to the security and decentralization of proof of stake networks, while providing increased liquidity and capital efficiency.
When a user deposits a token (ETH) into the Liquid Collective protocol, they receive a liquid staking token, that evidences legal and beneficial ownership of the staked ETH as well as any network rewards that accrue to the staked ETH, minus protocol service fees and network slashing penalties, if any. The receipt token can be transferred, stored, traded, and utilized in decentralized finance (DeFi) or supported decentralized apps (dapps).
LsETH is able to represent both staked ETH and any network rewards earned by following the , supporting LsETH's composability while providing participants with the ability to control their network reward flow
Liquid Collective offers to every participant via the to mitigate the risk of Node Operator failures and network outages
Liquid Collective's reduces correlation by spreading stake round-robin across a distributed network of Node Operators
Read on for Liquid Collective's ETH liquid staking protocol documentation.
Architecture
Liquid Collective's protocol architecture on Ethereum
Liquid Collective is designed to provide users with protections over protocol access via know-your-customer (KYC) and anti-money-laundering (AML) verification with to facilitate compliance
River is the core smart contract in the protocol. River manages:
LsETH Token
User Deposits: River allows users to perform ETH deposits and receive receipt tokens (mint LsETH) in return.
Consensus Layer Deposits: River orchestrates the delegation of ETH to validators and deposits to the official .
Oracle
The Oracle contract is responsible for feeding the River contract with the balance position of the validator nodes on the consensus layer. It relies on a set of Oracle Operators that periodically report data from the consensus layer to the execution layer; it is currently configured to report every 24 hours.
The Oracle contract helps synchronize a quorum of Oracle Operators to report the same consensus layer data. In particular, the Oracle contract makes sure that the core River contract receives data only after the Oracle contract has received identical reports from a quorum of Oracle Operators.
Node Operators Registry
The Node Operators Registry:
Manages Node Operators that have been approved to receive ETH delegation
Enables Node Operators to register validators
Selects the next validators to receive delegation, attempting even distribution so all Node Operators get a fair delegation
Allowlist
The Allowlist contract manages the permissions of who can deposit to the protocol. The protocol requires participants to use an allowlisted wallet to deposit ETH and redeem LsETH.
ELFeeRecipient
The ELFeeRecipient contract is the contract that receives execution layer fees, including priority fees and MEV network rewards.
Withdraw
The Withdraw contract is the contract that perceives withdrawn funds resulting from both validator’s full and partial exits. All Liquid Collective validator keys have their withdrawal credentials set to the address of the Withdraw contract. Withdrawn funds are automatically pushed to the Withdraw contract by design of the Ethereum protocol. Funds on the Withdraw contract are periodically pulled by River contract on every Oracle report.
Upgradeability
The Liquid Collective protocol smart contract was upgraded to enable LsETH redemptions in May of 2023. Liquid Collective upgradability relies on the upgradeable proxy pattern enabling any functional upgrade to the smart contracts.
In its current form, the River smart contract always sets the validator withdrawal credentials to the address of the Liquid Collective Withdraw contract, which is an upgradeable proxy Smart Contract.
Upgradability of both contracts is governed in a decentralized fashion by the protocol's administrators through the Liquid Collective DAO.
Queues, stacks, and buffers
Redemption Queue
The Liquid Collective protocol’s Redemption Queue facilitates the satisfaction of redemption requests in the same order as they have been requested. The first-in-first-out Redemption Queue is intended to protect against a race for claims in the event of high withdrawal demand.
Redemption Buffer
The Liquid Collective protocol’s Redemption Buffer holds ETH that is pending to be supplied for redemption satisfactions.
Withdrawal Stack
The Liquid Collective protocol’s Withdrawal Stack automatically facilitates the movement of ETH to the protocol’s Redemption Buffer. This ETH may be sourced by validator exits from the consensus layer or rebalanced from the protocol’s Deposit Buffer.
Deposit Buffer
The Liquid Collective protocol’s Deposit Buffer holds ETH pending to be deposited to Ethereum’s consensus layer, or that can be rebalanced to the Withdrawal Stack to programmatically facilitate redemption satisfactions. This ETH may be sourced from user deposits, network rewards (consensus layer & execution layer), the protocol’s Slashing Coverage Program, or rebalanced from the protocol’s Withdrawal Stack.
Liquid Collective allows users to deposit and stake any amount of ETH, not just 32 ETH (the minimum required to operate a full validator). Deposited ETH are gathered into an ETH smart contract account as fungible bulk. ETH in the account are regularly delegated to validators in a round-robin manner as the account reaches a balance of 32 ETH.
Each staker retains legal and beneficial ownership of an amount of ETH that is equivalent to the amount of ETH that was deposited by the staker, as evidenced by its LsETH receipt token. Receipt tokens like LsETH evidence legal and beneficial ownership of the deposited token, and ownership of the token is maintained throughout the life of the receipt token.
Self-custody
The Liquid Collective protocol is non-custodial. Deposited ETH is sent by the protocol to the Ethereum deposit contract. LsETH is also self-custodied, so LsETH holders have complete control over their LsETH and can pick any preferred custody solution.
IRedeemManagerV1
Allowlist
Allowlist Storage
Utility to manage the Allowlist mapping in storage
OracleMembers
Oracle Members Storage
Utility to manage the Oracle Members in storage
There can only be up to 256 oracle members. This is due to how report statuses are stored in Reports Positions
BufferedExceedingEth
Buffered Exceeding Eth storage
Redeem Manager utility to manage the exceeding ETH with a redeem request
RedeemManager
RedeemDemand
Redeem Demand storage
Redeem Manager utility to store the current demand in LsETH
River
RedeemQueueV2
Redeem Manager Redeem Queue storage
Utility to manage the Redeem Queue in the Redeem Manager
LastEpochId
Last Epoch Id Storage
Utility to manage the Last Epoch Id in storage
LibBasisPoints
Lib Basis Points
Holds the basis points max value
Libraries
LibAdministrable
Alluvial Finance Inc.
Lib Administrable
This library handles the admin and pending admin storage vars
LibSanitize
Lib Sanitize
Utilities to sanitize input values
TotalValidatorExitsRequested
TotalValidatorExitsRequested Storage
This value is the amount of performed exit requests, only increased when there is current exit demandUtility to manage the TotalValidatorExitsRequested in storage
LibUint256
Lib Uint256
Utilities to perform uint operations
OperatorsRegistry
Interfaces
State
LibUnstructuredStorage
Lib Unstructured Storage
Utilities to work with unstructured storage
CurrentValidatorExitsDemand
CurrentValidatorExitsDemand Storage
This value controls the current demand for exits that still need to be triggered in order to notify the operatorsUtility to manage the CurrentValidatorExitsDemand in storage
DenierAddress
Denier Address Storage
Utility to manage the Denier Address in storage
ReportsVariants
Reports Variants Storage
Utility to manage the Reports Variants in storage
WithdrawalStack
Redeem Manager Withdrawal Stack storage
Utility to manage the Withdrawal Stack in the Redeem Manager
CLValidatorCount
Consensus Layer Validator Count Storage
Utility to manage the Consensus Layer Validator Count in storageThis state variable is deprecated and was kept due to migration logic needs
BalanceToDeposit
AllowerAddress
Allower Address Storage
Utility to manage the Allower Address in storage
AllowList
Quorum
Quorum Storage
Utility to manage the Quorum in storage
Oracle
CLSpec
Consensus Layer Spec Storage
Utility to manage the Consensus Layer Spec in storage
Protocol Metadata
Liquid Collective protocol metadata
Liquid Collective protocol smart contracts expose a metadata URI that resolves to an IPFS directory containing resource files about the protocol.
Metadata directory contains different public resources such as:
Protocol Terms & Conditions
Marketing resources such as Liquid Collective logo pack
Security Audits reports
etc.
Any user can access the metadata by getting the IPFS URI from the River smart contracts and then retrieving the metadata directory from IPFS.
Below is an example of an RPC call to get Liquid Collective metadata URI using
Platform Operations
Platforms provide a seamless on-ramp and access for users to interact with the Liquid Collective protocol.
Platforms provide a seamless on-ramp and access for users to interact with the Liquid Collective protocol. There are two types of Liquid Collective Platforms.
Platforms that enable LsETH minting and redemption
These Platforms enable direct Liquid Collective protocol interactions, including depositing ETH to Ethereum's deposit contract and redeeming LsETH for ETH (minting and redeeming).
They conduct know-your-customer (KYC) and anti money laundering (AML) checks on their users, and submit approved user addresses to Liquid Collective's Allowlist.
These Platforms then provide a path to deposit and withdraw staked tokens.
In other words, KYC'd users who utilize a Platform's services can deposit to Liquid Collective and mint LsETH.
[!NOTE]
Users, also called stakers, are entities interested in staking ETH using the Liquid Collective protocol to mint the LsETH receipt token in return, evidencing their legal and beneficial ownership of the staked ETH plus rewards accrued and minus any fees or penalties. Before depositing ETH and minting LsETH, a user needs to go through an effective KYC/AML and sanctions screening process. After successfully completing the KYC/AML and sanctions screening process with a Platform, the user's wallet address can be added to Liquid Collective's Allowlist smart contract, authorizing deposit and redemption transactions.
Platforms that enable secondary interactions
These Platforms do not enable minting, redeeming, or direct Liquid Collective protocol interactions, but do enable secondary protocol interactions such as trading, lending, or other services not required to Allowlist KYC/AML wallet addresses.
Users of these Platforms can seamlessly interact with LsETH, and may accrue Ethereum's consensus and execution layer network rewards simply by holding LsETH.
By default, LsETH holders can transfer LsETH.
Enterprise integration APIs
The Liquid Collective protocol currently uses Alluvial's API services to facilitate Platform onboarding. Platform guides can be found in the .
Platforms offering KYC procedures for their users may submit user wallet addresses using the to register the addresses with the Liquid Collective Allowlist contract.
ProtocolMetrics
Methods
getRate
Returns
Name
Type
Description
initProtocolMetricsV1
Parameters
Name
Type
Description
Events
Initialize
Emitted when the contract is properly initialized
Parameters
Name
Type
Description
Errors
InvalidInitialization
An error occurred during the initialization
Parameters
Name
Type
Description
InvalidZeroAddress
The address is zero
LibBytes
Lib Bytes
This library helps manipulating bytes
Errors
SliceOutOfBounds
The slice is outside of the initial bytes bounds
SliceOverflow
The length overflows an uint
OperatorsV2
Operators Storage
Utility to manage the Operators in storage
Errors
OperatorNotFound
The operator was not found
Parameters
Name
Type
Description
Permissioning
Provide users with protections over protocol access for compliance, while ensuring composability with the rest of the DeFi ecosystem
Liquid Collective is designed to provide users with protections over protocol access via know-your-customer (KYC) and anti-money-laundering (AML) verification, while still ensuring composability with the rest of the DeFi ecosystem.
This facilitates compliance by providing the level of counterparty risk management required for enterprises and institutions to participate in staking on the protocol.
The Liquid Collective protocol:
Requires users to be on the Allowlist before they can deposit ETH or redeem LsETH
Initializable
Alluvial Finance Inc.
Initializable
This contract ensures that initializers are called only once per version
Events
IProtocolVersion
Methods
version
Retrieves the version of the contract
IDepositContract
Deposit Contract Interface
This interface exposes methods to perform validator deposits
Methods
LibErrors
Lib Errors
Library of common errors
Errors
ValidatorKeys
Validator Keys Storage
Utility to manage the validator keys in storage
Errors
function getRate() external view returns (uint256)
Enables users to transfer LsETH freely
Liquid Collective works with a variety of Platforms, including trading venues and custodians, to provide a seamless on-ramp for the protocol’s stakers. KYC’d users who utilize a Platform’s services to allowlist their wallet can deposit to Liquid Collective and mint LsTokens.
Allowlisting
Participation in Liquid Collective's smart contracts is restricted to allowlisted wallet addresses. This is meant for compliance purposes, ensuring that any user who wants to stake first completes a review and approval process (typically a know-your-business (KYB)/ know-your-customer (KYC) process).
The Liquid Collective Allowlist smart contract holds:
An Allowlister, which is a trusted party responsible for allowing users to participate in the Liquid Collective protocol. Typically Platforms that enable minting and redemption (ex. a custodial Platform performing KYC/AML checks on their customers) submit a user's wallet address to the Allowlister for subsequent addition to the Allowlist
An Allowlist of depositors with their permissions over the protocol (deposit, withdraw)
When a depositor wants to stake with the Liquid Collective protocol, their address must first be added to the Allowlist and be granted the corresponding permissions. Learn more about the type of Platforms that add users to the Allowlist in the Platform Operations documentation.
Access protections
To meet the compliance needs of Liquid Collective participants, the Liquid Collective protocol has an "access denial" mechanism for blocking individual Ethereum addresses from sending, receiving, minting, redeeming or claiming LsETH. The protocol does not have any mechanism for forcing a transfer of LsETH, reversing a transfer of LsETH or otherwise altering the balance of LsETH at an address.
The Liquid Collective's policy is that access will only be denied where there is a determination that not denying access to an address presents a threat to the security, integrity or reliability of the protocol. Examples of such circumstances include security breaches or legal requirements.
Requests by third parties for denial of access to an address must be submitted in writing to [email protected]. This policy and compliance with a request do not constitute acknowledgment or attornment by The Liquid Foundation or any other participant in the Liquid Collective to laws to which that participant is not already subject.
LsETH is a fungible receipt token based on the Ethereum ERC-20 cToken model. When a user deposits ETH to the Liquid Collective protocol, they receive an equivalent amount of LsETH that evidences their legal and beneficial ownership of the deposited ETH, as well as any network rewards that accrue to the ETH as a result of staking minus protocol service fees and network slashing penalties, if any.
Base L2: Verify the . The LsETH contract address is: 0xB29749498954A3A821ec37BdE86e386dF3cE30B6
LsETH User Agreement
By obtaining LsETH, participants agree to the terms of the , which remains in effect for as long as the participant holds LsETH.
The LsETH User Agreement is a legal agreement that outlines the terms and conditions of using the Liquid Collective protocol and holding LsETH. It contains important information about the protocol's token specifications and ownership characteristics, protocol service fees, slashing and slashing coverage, AML/KYC compliance, and risks associated with staking on Ethereum via the Liquid Collective protocol.
Each unit of LsETH is designed to serve as an electronic document of title to a corresponding amount of fungible ETH within the protocol. The LsETH User Agreement provides that LsETH is a cryptographic receipt that evidences legal and beneficial ownership of a corresponding amount of ETH, which is subject to increase as a result of the accrual of Ethereum network rewards.
To ensure open transparency into the agreement's terms, the LsETH User Agreement is additionally both encoded into the metadata of the LsETH smart contract and stored on-chain in IPFS .
You can learn more about the LsETH User Agreement and its innovations in our .
cToken
LsETH implements the , which uses a floating conversion rate—a.k.a. the protocol conversion rate—between a receipt token (e.g. LsETH) and the staked tokens to reflect the value of accrued network rewards, penalties, and fees associated with the staked tokens.
Because of the cToken design, LsETH's Conversion Rate may fluctuate. Depositors in the cToken model do not receive more or less tokens as their staked tokens accrue network rewards or penalties. Instead, the conversion rate for each cToken owned by the depositor will increase or decrease (i.e, the LsETH will evidence legal and beneficial ownership of more or less ETH) in an amount that reflects accrued network rewards or penalties. This is in contrast to other token models, such as aTokens, which issue new net network reward tokens on a unit basis.
Conversion Rate
The internal Conversion Rate is the rate at which Liquid Collective redeems LsETH from/to ETH on deposits and redemptions. In other words, the Conversion Rate is the amount of ETH for which LsETH can be redeemed. The Conversion Rate is independent of the price at which ETH or LsETH may trade on the open market.
The value of LsETH is bound to this internal Conversion Rate which fluctuates over time according to the network rewards earned by the validators. The Conversion Rate is computed as the total balance of staked ETH over the total supply of LsETH. If accrued network rewards are greater than penalties and fees, the internal Conversion Rate will increase to reflect the net network rewards collected by the protocol.
The Conversion Rate is updated every 24 hours at Oracle Report Time, which is when Liquid Collective accounts for network rewards earned.
Formula
At first deposit, the conversionRate is set to 1.
What can you do with LsETH?
Hold LsETH and accrue network rewards
Exchange LsETH for another token
Use LsETH as collateral to participate in a wide range of DeFi and dapp activities
What are the tax implications?
DISCLAIMER: This information is intended for informational purposes only and is not, and shall not be construed, to be any form of tax advice. All liquid staking participants are strongly encouraged to consult with their tax advisers to fully understand the tax implications of staking and liquid staking.
While the status of liquid staking activities under the Internal Revenue Code of 1986, as amended, remains uncertain, certain market views have developed around the U.S. tax consequences of liquid staking, including the following:
Depositing ETH and receiving LsETH may not be deemed a taxable event. Unlike a traditional token exchange (e.g., trading ETH for another token), depositing ETH may not be a token exchange because LsETH is a receipt token that evidences legal and beneficial ownership of the deposited ETH.
Additionally, because LsETH is based on the cToken model, the accrual of network rewards may not be deemed taxable events, especially when compared to the unit incremental basis in aToken models (or standard staking) for the accrual of network rewards.
Validator Infrastructure
Decentralized set of approved enterprise-grade Node Operators reduces the risks of validator operations
Validator Infrastructure
The Ethereum protocol requires validators to operate according to a pre-defined set of rules, and Node Operators are economically incentivized to follow those rules.
Under proper operational conditions, validators collect network rewards by proposing blocks and signing attestations
Under improper operational conditions, validators can miss network rewards, get penalized, or in worst case scenarios, get slashed
Liquid Collective is designed to provide a secure and enterprise-grade liquid staking solution which necessitates sanctions checks on the protocol’s active validator set. Liquid Collective works only with security-focused Node Operators that institute best practices to generate network rewards, including operating multi-region and multi-client infrastructure, technical support teams, and security posturing (including double-sign protection).
To reduce the risk impact of validator operations, and to increase decentralization, Liquid Collective delegates tokens to multiple independent validator Node Operators. The staked tokens are distributed across Node Operators in a round-robin manner so that the Liquid Collective protocol is supported by a broad and dispersed active validator set. As a result, the risk is distributed, which should minimize staked ETH exposure.
Node Operators in Liquid Collective's active set also support the protocol's by providing coverage for deductibles, up to a cap, against slashing incidents and missed rewards incurred due to the fault of their infrastructure.
Validator Node Operations
The Operators Registry contract provides facilities for Node Operators to register and manage validator keys on the Liquid Collective protocol. River regularly delegates ETH to Node Operators by funding and depositing validator keys to the Consensus Layer.
Before submitting validator keys for the first time, a Node Operator must complete Liquid Collective's Node Operator approval to be approved on the Operators Registry contracts. This one-time approval enables the Node Operator to register validator keys.
Generate Validator Key
For each validator key to be submitted to the Operators Registry contract, a Node Operator is required to:
Generate the corresponding DepositMessage and BLS12-381 signature as per the Ethereum 2.0 specifications
Set the fee recipient to the EL Fee Recipient contract, responsible for collecting execution layer network rewards
The protocol sets the validator's withdrawal credentials to the Liquid Collective Withdrawal contract address when the protocol initiates a deposit transaction for the validator.
Operator Registry Check
Once generated, the Node Operator registers one or more validator keys on the Operator Registry. The Liquid Foundation conducts a sanity check on the keys for compliance with the above requirements, before increasing the operator limit to make validator keys eligible to receive ETH to stake from the Liquid Collective protocol.
Activating Validators
Once a validator has been registered as eligible to receive ETH, its validators keys can be funded at any time. The Liquid Collective protocol regularly programmatically selects eligible validator keys, funds them, and deposits them to the official Ethereum deposit contract. Once deposited, validator keys enter the activation queue as per the standard Ethereum staking procedure.
Node Operator CLI
The Node Operator Command Line Interface is part of the tooling Liquid Collective provides to Node Operators to facilitate protocol operations. The application provides various commands to facilitate Node Operators' management of their validator keys.
To see a step by step workflow for the Node Operator CLI, check out the guide.
Oracle Infrastructure
Oracle operations on Liquid Collective report on consensus layer data
Members
The Oracle holds a list of the Oracle Operators' members who are expected to periodically report Consensus Layer data. These addresses can be checked via an off-chain naive search request.
The Oracle contract is configured such that a representative subset of those Operators are required to report the same Consensus Layer (also referred to as Beacon Chain) data before the Oracle contract reports to the River contract.
Quorum Synchronization
The Oracle is set to report Consensus Layer data to the River contract at configurable Consensus Layer epochs. For each reporting epoch, the Oracle contract expects a quorum of Oracle Operators to report the identical Consensus Layer data before reporting to the River contract.
Epochs
The Oracle contract is configurable so data is reported from a starting epoch and then for every epoch at a given interval.
In the current deployment, this interval is configured so consensus layer data is reported approximately every 24 hours.
Quorum
The Oracle contract holds a configurable quorum value that indicates the minimum number of Oracle Operators that must report identical Consensus Layer data before reporting the data to the River contract.
At each reporting epoch, every Oracle Operator is expected to collect Consensus Layer data and report it to the Oracle contract through a transaction. The Oracle contract counts the reported consensus layer balance sum of Liquid Collective validators, the reported count of validators, and the number of similar reports from Oracle Operators, along with the count of report variants.
Any changes to the quorum, such as removing Oracle Operators from the members list, clears all of the reporting data for that epoch. Remaining Oracle Operators that had already submitted reports for that epoch would need to report again for the same epoch.
Once receiving a quorum of identical reports, the Oracle contract publishes the data to the River contract, at which point the River contract can compute and distribute network rewards.
Reports
The Oracle contract aims to report the following data to the River contract:
Epoch - The epoch for which the Consensus Layer data corresponds to.
Validators Count – The count of active Liquid Collective validators on the Consensus Layer (either in status active or active_ongoing). This is necessary so River can compute the number of validators in pending status that have been staked to on the Deposit Contract but are not yet active on the Consensus Layer.
Sanity Checks
The Oracle contract is responsible for performing certain sanity checks on the reported data, providing a layer of security to the protocol in case Oracle Operators behave maliciously.
First, the Oracle contract makes sure that the Oracle Operator's reported transactions are for the correct expected epoch.
Second, it makes sure that the validators' reported balances are coherent. In particular, the Oracle contract:
Forbids Oracle Operators from reporting earned rewards that would exceed some configurable upper bound of APY. This upper bound takes into account the APY delta between updates extrapolated on a yearly time frame.
Forbids Oracle Operators from reporting a balance that would have decreased more than some configurable lower bound of fees or penalties. This lower bound is based on the relative balance decrease.
The execution layer fees are taken into account in these sanity checks as they are the product of a Node Operator's work, just like consensus layer fees.
Oracle Data
The Oracle contract receives reports from the Oracle Operators and updates the following data for the River contract:
Validators Count – The count of active Liquid Collective validators on the Consensus Layer (either in status active or posterior). This count is necessary to compute the count of Liquid Collective validators in pending status that have been funded and deposited to the Deposit Contract but are not yet active on the Consensus Layer.
Validators Balance – The total ETH balance of active Liquid Validators on the Consensus Layer.
Each time a new report is processed, if Liquid Collective's validators have collectively earned a positive network reward, then this network reward is distributed between parties involved in the Liquid Collective protocol by increasing the Conversion Rate for LsETH.
UserDepositManagerV1
Alluvial Finance Inc.
User Deposit Manager (v1)
This contract handles the inbound transfers cases or the explicit submissions
Methods
deposit
Explicit deposit method to mint on msg.sender
depositAndTransfer
Explicit deposit method to mint on msg.sender and transfer to _recipient
Parameters
Name
Type
Description
Events
UserDeposit
User deposited ETH in the system
Parameters
Name
Type
Description
Errors
EmptyDeposit
And empty deposit attempt was made
InvalidCall
The call was invalid
InvalidZeroAddress
The address is zero
IAdministrable
Alluvial Finance Inc.
Administrable Interface
This interface exposes methods to handle the ownership of the contracts
Methods
acceptAdmin
Accept the transfer of ownership
Only callable by the pending admin. Resets the pending admin if successful.
getAdmin
Retrieves the current admin address
Returns
Name
Type
Description
getPendingAdmin
Retrieve the current pending admin address
Returns
Name
Type
Description
proposeAdmin
Proposes a new address as admin
This security prevents setting an invalid address as an admin. The pending admin has to claim its ownership of the contract, and prove that the new address is able to perform regular transactions.
Parameters
Name
Type
Description
Events
SetAdmin
The admin address changed
Parameters
Name
Type
Description
SetPendingAdmin
The pending admin address changed
Parameters
Name
Type
Description
IUserDepositManagerV1
Alluvial Finance Inc.
User Deposit Manager (v1)
This interface exposes methods to handle the inbound transfers cases or the explicit submissions
Methods
deposit
Explicit deposit method to mint on msg.sender
depositAndTransfer
Explicit deposit method to mint on msg.sender and transfer to _recipient
Parameters
Name
Type
Description
Events
UserDeposit
User deposited ETH in the system
Parameters
Name
Type
Description
Errors
EmptyDeposit
And empty deposit attempt was made
IELFeeRecipientV1
Alluvial Finance Inc.
Execution Layer Fee Recipient Interface (v1)
This interface exposes methods to receive all the execution layer fees from the proposed blocks + bribes
Methods
initELFeeRecipientV1
Initialize the fee recipient with the required arguments
Parameters
Name
Type
Description
pullELFees
Pulls ETH to the River contract
Only callable by the River contract
Parameters
Name
Type
Description
Events
SetRiver
The storage river address has changed
Parameters
Name
Type
Description
Errors
InvalidCall
The fallback has been triggered
IWithdrawV1
Alluvial Finance Inc.
Withdraw Interface (V1)
This contract is in charge of holding the exit and skimming funds and allow river to pull these funds
Methods
getCredentials
Retrieve the withdrawal credentials to use
Returns
Name
Type
Description
getRiver
Retrieve the linked River address
Returns
Name
Type
Description
initializeWithdrawV1
Parameters
Name
Type
Description
pullEth
Callable by River, sends the specified amount of ETH to River
Parameters
Name
Type
Description
Events
SetRiver
Emitted when the linked River address is changed
Parameters
Name
Type
Description
Slashing Coverage
Three layers of slashing coverage are available for every participant staking through the Liquid Collective protocol
Slashing Coverage enables certain Liquid Collective partners to reimburse LsETH holders following a slashing incident. Liquid Collective's Slashing Coverage Program is included in the ; as such, participation in the program requires no further action than holding LsETH.
includes three layers of coverage: Nexus Mutual Coverage, the Slashing Coverage Treasury, and the Node Operator Commitment. The program covers both network-wide events—such as network outages—and node operator failures.
Deployment Addresses
Liquid Collective deployment addresses
Contract
Mainnet
Hoodi
Administrable
Alluvial Finance Inc.
Administrable
This contract handles the administration of the contracts
Methods
ICoverageFundV1
Alluvial Finance Inc.
Coverage Fund Interface (v1)
This interface exposes methods to receive donations for the slashing coverage fund and pull the funds into river
Slashing Coverage Program Summary: 3 layers of coverage
You can find more details about Liquid Collective's Slashing Coverage Program in this blog post.
1. Nexus Mutual Coverage
Nexus Mutual is the leading provider of decentralized crypto-native protection, having secured billions of dollars in value held in smart contracts. Nexus Mutual’s bespoke Slashing Coverage for Liquid Collective is fully scalable coverage that dynamically adjusts with the protocol's assets on platform (AoP) and provides access to Nexus Mutual's slashing coverage directly from a user's custody account at platforms such as Coinbase or Bitcoin Suisse.
2. Slashing Coverage Treasury
Liquid Collective’s Slashing Coverage Treasury allocates a percentage of all network rewards to provide coverage for slashing coverage deductibles on network-wide slashing incidents. The Treasury continues to accrue network rewards unless deployed.
3. Node Operator Commitment
Node operators supporting Liquid Collective's active set provide coverage for deductibles, up to a cap, against slashing incidents and missed rewards incurred due to the fault of their infrastructure.
Slashing Coverage Fund
The Slashing Coverage Fund is in charge of injecting coverage funds into the system. In the case of a slashing event on one of the validators of the system, the Slashing Coverage Fund can be supplied with ETH to be used to repay slashing losses. When funds are sent to the Slashing Coverage Fund, the system will attempt to pull everything until the fund is empty.
The amount pulled is always capped by the reporting upper bound, just like the execution layer fees. This means that the supplied ETH will probably be injected in the system in multiple oracle report rounds.
Slashing Coverage Fund Contract
The Slashing Coverage Fund contract enables the Liquid Collective Slashing Coverage Program. The contract receives the funds to distribute for the slashing coverage, which are used to cover losses that may occur on the consensus layer due to slashing events. The contract acts as a temporary buffer for funds that can be pulled in case of a loss.
Fund Supply
Funds are supplied to the Slashing Coverage Fund contract when a qualified slashing event has occurred.
Partners assigned with a deductible can reimburse by posting the deductible (in ETH) to Liquid Collective's CoverageFund smart contract. ETH in the CoverageFund contract are periodically pulled into the system, accounted into the Conversion Rate, and eventually introduced into the staking flow.
Liquid Collective's CoverageFund contract is designed to only accept ETH from allowlisted accounts with a specific DONATOR permission.
When pulling funds from the CoverageFund contract the system does not mint any new LsETH and so the operation results in a replacement of any shortfalls that may have occurred from a slashing event, which applies to every LsETH holder.
Fund Distribution
No fees are taken on the received funds
The funds are entirely distributed to LsETH holders
No new LsETH are minted
Funds are distributed by increasing the Conversion Rate of LsETH
Funds from the CoverageFund contract are pulled into the system upon successful Oracle reports after Execution Layer fees have been pulled and rewards have been accounted, so no fee is charged on the cover funds pulled.
The amount pulled from the CoverageFund contract respects the Conversion Rate's variation bounds, so a slashing reimbursement cannot disrupt the Conversion Rate. On every Oracle report the system accounts for network rewards (CL + EL) then collects the gross fee, then attempts to pull funds from the CoverageFund contract up to the authorized maximum to remain within Conversion Rate's variation bounds.
In other words, if ETH is available in the contract, River will attempt to pull as much ETH as possible, up to the upper bound allowed by the Oracle contract. This smoothing mechanism means that it may take multiple Oracle cycles for Slashing Coverage Funds to be pulled entirely into the system, ensuring a gradual variation of the Conversion Rate.
Only callable by the pending admin. Resets the pending admin if successful.
getAdmin
Retrieves the current admin address
Returns
Name
Type
Description
_0
address
The admin address
getPendingAdmin
Retrieve the current pending admin address
Returns
Name
Type
Description
_0
address
The pending admin address
proposeAdmin
Proposes a new address as admin
This security prevents setting an invalid address as an admin. The pending admin has to claim its ownership of the contract, and prove that the new address is able to perform regular transactions.
Parameters
Name
Type
Description
_newAdmin
address
New admin address
Events
SetAdmin
The admin address changed
Parameters
Name
Type
Description
admin indexed
address
New admin address
SetPendingAdmin
The pending admin address changed
Parameters
Name
Type
Description
pendingAdmin indexed
address
New pending admin address
Errors
InvalidZeroAddress
The address is zero
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
caller
address
Address performing the call
donate
Donates ETH to the coverage fund contract
initCoverageFundV1
Initialize the coverage fund with the required arguments
Parameters
Name
Type
Description
_riverAddress
address
Address of River
pullCoverageFunds
Pulls ETH into the River contract
Only callable by the River contract
Parameters
Name
Type
Description
_maxAmount
uint256
The maximum amount to pull into the system
Events
Donate
A donation has been made to the coverage fund
Parameters
Name
Type
Description
donator indexed
address
Address that performed the donation
amount
uint256
The amount donated
SetRiver
The storage river address has changed
Parameters
Name
Type
Description
river indexed
address
The new river address
Errors
EmptyDonation
A donation with 0 ETH has been performed
InvalidCall
The fallback or receive callback has been triggered
function deposit() external payable
function depositAndTransfer(address _recipient) external payable
The collection and socialization of Ethereum network rewards and Liquid Collective protocol fees
Every 24 hours, Oracles report the new balance of staked ETH from accrued network rewards or fees. The Conversion Rate is computed as the total balance of staked ETH over the total supply of LsETH. If accrued network rewards are greater than penalties and fees, the protocol Conversion Rate increases to reflect the net Ethereum network rewards collected by the protocol.
Because of LsETH's cToken design, the Conversion Rate may fluctuate. In contrast to other token models, such as aTokens, that issue new net network reward tokens on a unit basis, stakers on the Liquid Collective protocol will not receive more or less tokens as they receive network rewards or penalties.
Instead, the Conversion Rate for each unit of LsETH owned by the depositor will increase or decrease (i.e., the LsETH will evidence legal and beneficial ownership of more or less ETH) in an amount that reflects accrued network rewards.
Protocol Service Fee
The Liquid Collective protocol charges a Protocol Service Fee set at 10.0% of network rewards. Liquid Collective’s service fee is split amongst split amongst Node Operators, Platforms, Wallet & Custody Providers, Service Providers, the protocol’s , and the Liquid Collective DAO, which comprises a broad and dispersed community of protocol participants. All service fees are distributed in LsTokens, which are the native receipt tokens of the protocol (e.g. LsETH).
Every day the Liquid Collective protocol accounts for Ethereum network rewards including consensus layer network rewards and execution layer fees minus possible penalties, which results in updating the data reflecting the total supply of ETH.
If network rewards have been earned on a given day, then the protocol collects the Protocol Service Fee as a percentage of the earned network rewards. The Protocol Service Fee is collected by minting LsETH, which results in an increase in the total supply of LsETH.
Under normal validator operations, the protocol earns network rewards; as such the total supply of ETH increases and the Conversion Rate increases accordingly.
In a scenario where validators are penalized or slashed, depending on the magnitude of the incurred penalties, the total ETH supply could decrease, and the Conversion Rate would decrease accordingly.
Example
Assuming
totalETHSupply = 125 ETH
totalLsETHSupply = 100
Note: Figures above are just examples and do not reflect reality or projections.
Calculating rewards and fees
Each time the Oracle contract reports consensus layer data to the River contract, the protocol programmatically distributes network rewards including consensus layer network rewards and execution layer fees.
Fees received by validators for the execution of transactions are distributed on the execution layer directly. The Liquid Collective protocol automatically stakes the execution layer fees to increase the protocol’s overall potential reward rate by increasing the number of validators in the protocol's active set.
Network reward computation
Each time the Oracle reports consensus layer data, the River smart contract:
Pulls execution layer fees from the EL Fee Recipient contract
Updates consensus layer data including the Liquid Collective active validators count and total Liquid Collective active validators balance
The network reward is computed as:
EL Fee Recipient Contract
The EL Fee Recipient Contract receives all of the execution layer fees including transaction fees and MEV priority fees. The River contract periodically pulls that ETH on every Oracle report.
Network reward distribution
If the earned reward is positive, it is distributed between:
LsETH holders receive 85% of the network rewards, proportional to their LsETH holdings, through an accrual of the Conversion Rate
Collector that receives the Protocol Service Fee via minting LsETH, which is currently set at 10%
Reward and penalty socialization
Liquid Collective socializes network rewards and penalties between holders proportionally to their LsETH balance. The protocol aims to enforce fairness between participants, making sure that no participant gets treated favorably compared to others.
This means that stakers on Liquid Collective are exposed to the performance of all validators across Liquid Collective as a whole.
Examples:
If a validator receives a massive MEV network reward, then this network reward is socialized amongst every LsETH holder.
If a validator gets slashed, then the penalty is socialized amongst every LsETH holder.
This socialization of network rewards and penalties is realized by the LsETH Conversion Rate which applies to every LsETH holder equally. Every 24 hours, Oracle reports the new balance of staked ETH across the protocol accounting for accrued network rewards and penalties, resulting in updating the Conversion Rate, which applies to every LsETH holder.
ELFeeRecipientV1
Alluvial Finance Inc.
Execution Layer Fee Recipient (v1)
This contract receives all the execution layer fees from the proposed blocks + bribes
Methods
initELFeeRecipientV1
Initialize the fee recipient with the required arguments
Parameters
Name
Type
Description
pullELFees
Pulls ETH to the River contract
Only callable by the River contract
Parameters
Name
Type
Description
version
Retrieves the version of the contract
Returns
Name
Type
Description
Events
Initialize
Emitted when the contract is properly initialized
Parameters
Name
Type
Description
SetRiver
The storage river address has changed
Parameters
Name
Type
Description
Errors
InvalidCall
The fallback has been triggered
InvalidInitialization
An error occurred during the initialization
Parameters
Name
Type
Description
InvalidZeroAddress
The address is zero
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
WithdrawV1
Alluvial Finance Inc.
Withdraw (v1)
This contract is in charge of holding the exit and skimming funds and allow river to pull these funds
Methods
getCredentials
Retrieve the withdrawal credentials to use
Returns
Name
Type
Description
getRiver
Retrieve the linked River address
Returns
Name
Type
Description
initializeWithdrawV1
Parameters
Name
Type
Description
pullEth
Callable by River, sends the specified amount of ETH to River
Parameters
Name
Type
Description
version
Retrieves the version of the contract
Returns
Name
Type
Description
Events
Initialize
Emitted when the contract is properly initialized
Parameters
Name
Type
Description
SetRiver
Emitted when the linked River address is changed
Parameters
Name
Type
Description
Errors
InvalidInitialization
An error occurred during the initialization
Parameters
Name
Type
Description
InvalidZeroAddress
The address is zero
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
TUPProxy
Alluvial Finance Inc.
TUPProxy (Transparent Upgradeable Pausable Proxy)
This contract extends the Transparent Upgradeable proxy and adds a system wide pause feature. When the system is paused, the fallback will fail no matter what calls are made. Address Zero is allowed to perform calls even if paused to allow view calls made from RPC providers to properly work.
Methods
pause
Pauses system
paused
Retrieves Paused state
Returns
Name
Type
Description
unpause
Unpauses system
Events
AdminChanged
Emitted when the admin account has changed.
Parameters
Name
Type
Description
BeaconUpgraded
Emitted when the beacon is changed.
Parameters
Name
Type
Description
Paused
The system is now paused
Parameters
Name
Type
Description
Unpaused
The system is now unpaused
Parameters
Name
Type
Description
Upgraded
Emitted when the implementation is upgraded.
Parameters
Name
Type
Description
Errors
CallWhenPaused
A call happened while the system was paused
IFirewall
Figment
Firewall
This interface exposes methods to accept calls to admin-level functions of an underlying contract.
Methods
protocolFee = 10%
So conversionRate = 125 / 100 = 1.25
Today the protocol earns 10 ETH thus the protocol fee is 10% * 10 ETH / 1.25 = 0.8 LsETH
And the new conversionRate = (125+10) / (108+0.8) = 1.58
This contract receive donations for the slashing coverage fund and pull the funds into riverThis contract acts as a temporary buffer for funds that should be pulled in case of a loss of money on the consensus layer due to slashing events.There is no fee taken on these funds, they are entirely distributed to the LsETH holders, and no shares will get minted.Funds will be distributed by increasing the underlying value of every LsETH share.The fund will be called on every report and if eth is available in the contract, River will attempt to pull as much ETH as possible. This maximum is defined by the upper bound allowed by the Oracle. This means that it might take multiple reports for funds to be pulled entirely into the system due to this upper bound, ensuring a lower secondary market impact.The value provided to this contract is computed off-chain and provided manually by Alluvial or any authorized insurance entity.The Coverage funds are pulled upon an oracle report, after the ELFees have been pulled in the system, if there is a margin left before crossing the upper bound. The reason behind this is to favor the revenue stream, that depends on market and network usage, while the coverage fund will be pulled after the revenue stream, and there won't be any commission on the eth pulled.Once a Slashing event occurs, the team will do its best to inject the recovery funds in at maximum 365 days. The entities allowed to donate are selected by the team. It will mainly be treasury entities or insurance protocols able to fill this coverage fund properly.
IConsensusLayerDepositManagerV1
Alluvial Finance Inc.
Consensys Layer Deposit Manager Interface (v1)
This interface exposes methods to handle the interactions with the official deposit contract
Methods
Methods
donate
Donates ETH to the coverage fund contract
initCoverageFundV1
Initialize the coverage fund with the required arguments
Parameters
Name
Type
Description
_riverAddress
address
Address of River
pullCoverageFunds
Pulls ETH into the River contract
Only callable by the River contract
Parameters
Name
Type
Description
_maxAmount
uint256
The maximum amount to pull into the system
version
Retrieves the version of the contract
Returns
Name
Type
Description
_0
string
Version of the contract
Events
Donate
A donation has been made to the coverage fund
Parameters
Name
Type
Description
donator indexed
address
Address that performed the donation
amount
uint256
The amount donated
Initialize
Emitted when the contract is properly initialized
Parameters
Name
Type
Description
version
uint256
New version of the contracts
cdata
bytes
Complete calldata that was used during the initialization
SetRiver
The storage river address has changed
Parameters
Name
Type
Description
river indexed
address
The new river address
Errors
EmptyDonation
A donation with 0 ETH has been performed
InvalidCall
The fallback or receive callback has been triggered
InvalidInitialization
An error occurred during the initialization
Parameters
Name
Type
Description
version
uint256
The version that was attempting to be initialized
expectedVersion
uint256
The version that was expected
InvalidZeroAddress
The address is zero
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
caller
address
Address performing the call
depositToConsensusLayerWithDepositRoot
Deposits current balance to the Consensus Layer by batches of 32 ETH
Parameters
Name
Type
Description
_maxCount
uint256
The maximum amount of validator keys to fund
_depositRoot
bytes32
The root of the deposit tree
getBalanceToDeposit
Returns the amount of ETH not yet committed for deposit
Returns
Name
Type
Description
_0
uint256
The amount of ETH not yet committed for deposit
getCommittedBalance
Returns the amount of ETH committed for deposit
Returns
Name
Type
Description
_0
uint256
The amount of ETH committed for deposit
getDepositedValidatorCount
Get the deposited validator count (the count of deposits made by the contract)
Returns
Name
Type
Description
_0
uint256
The deposited validator count
getKeeper
Get the keeper address
Returns
Name
Type
Description
_0
address
The keeper address
getWithdrawalCredentials
Retrieve the withdrawal credentials
Returns
Name
Type
Description
_0
bytes32
The withdrawal credentials
Events
SetDepositContractAddress
The stored deposit contract address changed
Parameters
Name
Type
Description
depositContract indexed
address
Address of the deposit contract
SetDepositedValidatorCount
Emitted when the deposited validator count is updated
Parameters
Name
Type
Description
oldDepositedValidatorCount
uint256
The old deposited validator count value
newDepositedValidatorCount
uint256
The new deposited validator count value
SetWithdrawalCredentials
The stored withdrawal credentials changed
Parameters
Name
Type
Description
withdrawalCredentials
bytes32
The withdrawal credentials to use for deposits
Errors
ErrorOnDeposit
An error occurred during the deposit
InconsistentPublicKeys
The length of the BLS Public key is invalid during deposit
InconsistentSignatures
The length of the BLS Signature is invalid during deposit
InvalidDepositRoot
Invalid deposit root
InvalidPublicKeyCount
The received count of public keys to deposit is invalid
InvalidSignatureCount
The received count of signatures to deposit is invalid
InvalidWithdrawalCredentials
The withdrawal credentials value is null
NoAvailableValidatorKeys
The internal key retrieval returned no keys
NotEnoughFunds
Not enough funds to deposit one validator
OnlyKeeper
function donate() external payable
function initCoverageFundV1(address _riverAddress) external nonpayable
function pullCoverageFunds(uint256 _maxAmount) external nonpayable
This contract handles the interactions with the official deposit contract, funding all validatorsWhenever a deposit to the consensus layer is requested, this contract computed the amount of keys that could be deposited depending on the amount available in the contract. It then tries to retrieve validator keys by calling its internal virtual method _getNextValidators. This method should be overridden by the implementing contract to provide [0; _keyCount] keys when invoked.
Methods
DEPOSIT_SIZE
Size of a deposit in ETH
Returns
Name
Type
Description
PUBLIC_KEY_LENGTH
Size of a BLS Public key in bytes
Returns
Name
Type
Description
SIGNATURE_LENGTH
Size of a BLS Signature in bytes
Returns
Name
Type
Description
depositToConsensusLayerWithDepositRoot
Deposits current balance to the Consensus Layer by batches of 32 ETH
Parameters
Name
Type
Description
getBalanceToDeposit
Returns the amount of ETH not yet committed for deposit
Returns
Name
Type
Description
getCommittedBalance
Returns the amount of ETH committed for deposit
Returns
Name
Type
Description
getDepositedValidatorCount
Get the deposited validator count (the count of deposits made by the contract)
Returns
Name
Type
Description
getKeeper
Get the keeper address
Returns
Name
Type
Description
getWithdrawalCredentials
Retrieve the withdrawal credentials
Returns
Name
Type
Description
Events
SetDepositContractAddress
The stored deposit contract address changed
Parameters
Name
Type
Description
SetDepositedValidatorCount
Emitted when the deposited validator count is updated
Parameters
Name
Type
Description
SetWithdrawalCredentials
The stored withdrawal credentials changed
Parameters
Name
Type
Description
Errors
ErrorOnDeposit
An error occurred during the deposit
InconsistentPublicKeys
The length of the BLS Public key is invalid during deposit
InconsistentSignatures
The length of the BLS Signature is invalid during deposit
InvalidDepositRoot
Invalid deposit root
InvalidPublicKeyCount
The received count of public keys to deposit is invalid
InvalidSignatureCount
The received count of signatures to deposit is invalid
InvalidWithdrawalCredentials
The withdrawal credentials value is null
NoAvailableValidatorKeys
The internal key retrieval returned no keys
NotEnoughFunds
Not enough funds to deposit one validator
OnlyKeeper
SliceOutOfBounds
The slice is outside of the initial bytes bounds
SliceOverflow
The length overflows an uint
_0
uint256
undefined
_0
uint256
undefined
_0
uint256
undefined
_maxCount
uint256
The maximum amount of validator keys to fund
_depositRoot
bytes32
The root of the deposit tree
_0
uint256
The amount of ETH not yet committed for deposit
_0
uint256
The amount of ETH committed for deposit
_0
uint256
The deposited validator count
_0
address
The keeper address
_0
bytes32
The withdrawal credentials
depositContract indexed
address
Address of the deposit contract
oldDepositedValidatorCount
uint256
The old deposited validator count value
newDepositedValidatorCount
uint256
The new deposited validator count value
withdrawalCredentials
bytes32
The withdrawal credentials to use for deposits
function DEPOSIT_SIZE() external view returns (uint256)
function PUBLIC_KEY_LENGTH() external view returns (uint256)
function SIGNATURE_LENGTH() external view returns (uint256)
function depositToConsensusLayerWithDepositRoot(uint256 _maxCount, bytes32 _depositRoot) external nonpayable
function getBalanceToDeposit() external view returns (uint256)
function getCommittedBalance() external view returns (uint256)
function getDepositedValidatorCount() external view returns (uint256)
function getKeeper() external view returns (address)
function getWithdrawalCredentials() external view returns (bytes32)
This contract accepts calls to admin-level functions of an underlying contract, and ensures the caller holds an appropriate role for calling that function. There are two roles:
An Admin can call anything
An Executor can call specific functions
The list of function is customizable. Random callers cannot call anything through this contract, even if the underlying function is unpermissioned in the underlying contract. Calls to non-admin functions should be called at the underlying contract directly.
Methods
acceptAdmin
Accept the transfer of ownership
Only callable by the pending admin. Resets the pending admin if successful.
allowExecutor
Sets the permission for a function selector
Parameters
Name
Type
Description
destination
Retrieve the destination address
Returns
Name
Type
Description
executor
Retrieve the executor address
Returns
Name
Type
Description
executorCanCall
Returns true if the executor is allowed to perform a call on the given selector
Parameters
Name
Type
Description
Returns
Name
Type
Description
getAdmin
Retrieves the current admin address
Returns
Name
Type
Description
getPendingAdmin
Retrieve the current pending admin address
Returns
Name
Type
Description
proposeAdmin
Proposes a new address as admin
This security prevents setting an invalid address as an admin. The pending admin has to claim its ownership of the contract, and prove that the new address is able to perform regular transactions.
Parameters
Name
Type
Description
setExecutor
Sets the executor address
Parameters
Name
Type
Description
version
Retrieves the version of the contract
Returns
Name
Type
Description
Events
SetAdmin
The admin address changed
Parameters
Name
Type
Description
SetDestination
The stored destination address has been changed
Parameters
Name
Type
Description
SetExecutor
The stored executor address has been changed
Parameters
Name
Type
Description
SetExecutorPermissions
The storage permission for a selector has been changed
Parameters
Name
Type
Description
SetPendingAdmin
The pending admin address changed
Parameters
Name
Type
Description
Errors
InvalidZeroAddress
The address is zero
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
_functionSelector
bytes4
Method signature on which the permission is changed
_executorCanCall
bool
True if selector is callable by the executor
_0
address
The destination address
_0
address
The executor address
_0
bytes4
undefined
_0
bool
True if executor is allowed to call
_0
address
The admin address
_0
address
The pending admin address
_newAdmin
address
New admin address
_newExecutor
address
New address for the executor
_0
string
Version of the contract
admin indexed
address
New admin address
destination indexed
address
The new destination address
executor indexed
address
The new executor address
selector
bytes4
The 4 bytes method selector
status
bool
True if executor is allowed
pendingAdmin indexed
address
New pending admin address
caller
address
Address performing the call
function acceptAdmin() external nonpayable
function allowExecutor(bytes4 _functionSelector, bool _executorCanCall) external nonpayable
function destination() external view returns (address)
function executor() external view returns (address)
function executorCanCall(bytes4) external view returns (bool)
function getAdmin() external view returns (address)
function getPendingAdmin() external view returns (address)
function proposeAdmin(address _newAdmin) external nonpayable
function setExecutor(address _newExecutor) external nonpayable
Staking ETH to mint LsETH, and redeeming LsETH for ETH, on Liquid Collective
Liquid Collective users can deposit ETH to stake on Ethereum. Users can also redeem LsETH for the underlying staked ETH plus network rewards earned, and minus any fees or penalties.
Note: Depending on the amount of ETH the protocol's Deposit Buffer, a validator may need to be exited from Ethereum to service a LsETH redemption request. When a validator is exited, it is subject to the Ethereum network's variable exit and withdrawal queues, which can take minutes to days. It's recommended to review the current maximum exit queue and withdraw queue times here.
Deposit and Redemption Buffers
The Liquid Collective protocol automatically maintains ETH Deposit and Redemption Buffers. These buffers are designed to ensure that flows in and out of the protocol are managed efficiently between Ethereum’s execution and consensus layers, which enables seamless redemptions of LsETH for ETH via automatic rebalancing.
The protocol’s Deposit Buffer includes ETH pending to be deposited to Ethereum’s consensus layer, while the Redemption Buffer includes ETH pending to be supplied for redemptions.
ETH deposits enter the Deposit Buffer to be programmatically staked in Ethereum’s consensus layer
Ethereum execution layer fees received by Liquid Collective validators automatically enter the Deposit Buffer to be programmatically staked
Ethereum consensus layer network rewards received by Liquid Collective validators automatically enter the Deposit Buffer to be programmatically staked
Queues, stacks, and buffers
In addition to the Liquid Collective protocol’s Deposit and Redemption Buffers, the protocol’s Withdrawal Stack, along with Ethereum’s activation and exit queues, play an important role in deposits and redemptions on the Liquid Collective protocol.
Visualization of Withdrawal Stack, Redemption Queue, and Deposit and Redemption Buffers
Below is a step-by-step diagram showing how a request will flow through the protocol’s buffers and stacks.
Deposit ETH
When a user deposits ETH they receive the LsETH receipt token at the current Conversion Rate, which evidences legal and beneficial ownership of the staked token, plus network rewards received and minus any fees or penalties.
Deposited ETH automatically enters the Liquid Collective protocol’s Deposit Buffer. As ETH in the Deposit Buffer reaches a fungible bulk of 32 ETH it is programmatically staked, funding new validator keys and being pushed to Etheruem’s activation queue.
LsETH are minted on deposit, so depositing does not affect the Conversion Rate.
Example
Assuming
totalETHSupply = 125 ETH
totalLsETHSupply = 100 LsETH
So conversionRate = 125 / 100 = 1.25
Note: Figures above are just examples and do not reflect reality or projections.
Interface level smart contract flow
For more technical audiences, a sequence diagram showing the interaction between smart contracts is included below:
For those that want to view a stack trace, we recommend using a tool like .
Here is a sample transaction hash on mainnet: Deposit: 0xace4dc0272645d9e0120f25a478d1b7375cc42dd4b1c0369bd00d02847e54e25 Oracle Report: 0x67d44ab16ece7c2adcc97b538359f4c21fc10a09413d7014962c5dc5b79e4cb0
Redeem LsETH
The LsETH receipt token can be redeemed for ETH at the current Conversion Rate, to effectively withdraw the staked token plus network rewards received and minus any fees or penalties.
Redemption requests on the Liquid Collective protocol cannot be canceled once they have been made. This is because validator exits cannot be canceled on Ethereum once they have been triggered.
Three-stage redemption process
LsETH redemptions take place via a three-stage process performed programmatically by the Liquid Collective protocol:
Request: the LsETH holder requests a redemption via a Platform (e.g. in the Coinbase Prime app), surrendering the amount of LsETH that they would like to redeem. This LsETH will eventually be burned.
Satisfaction: after the protocol completes any required validator exits and the corresponding amount of ETH is withdrawn as according to the protocol Conversion Rate, the request is satisfied and can be claimed at any time.
Claim: the redemption request is claimed, triggering the actual transfer of ETH to the redeemer.
Redemption architecture
When a LsETH holder requests a redemption the request is added to the protocol’s Redemption Queue. On each Oracle report, completed approximately every 24 hours, the protocol assesses the unsupplied ETH demand for redemptions.
When there is unsupplied ETH demand:
The Liquid Collective protocol programmatically rebalance's ETH between the deposit and Redemption Buffers to preserve capital efficiency by minimizing consensus layer operations. The protocol prioritizes moving ETH from the Deposit Buffer to the Redemption Buffer to satisfy the unsupplied redemption requests.
If there is still unsupplied redemption demand, the protocol requests validator exits by signaling Node Operators. Upon receiving this request, the appropriate number of validators are entered to Ethereum’s exit queue, where they are subject to .
All Liquid Collective validator keys have their withdrawal credentials set to the address of Liquid Collective’s Withdraw contract, which is automatically pulled to the Redemption Buffer upon Oracle report. The withdrawn ETH is then used by the protocol to satisfy the unsupplied redemptions.
A user decides they want to redeem their LsETH for ETH via the Liquid Collective protocol
A user's redemption request is enqueued in the Redemption Queue pending satisfaction
On each Oracle report, the Liquid Collective protocol evaluates pending LsETH redemption requests and programmatically pulls any ETH from the Deposit Buffer to the Redemption Buffer to satisfy the requests
Most stakers can complete this process easily via their preferred Liquid Collective Platform (e.g. in the Coinbase Prime app). At the protocol level, at a high level this request process is executed via interacting with the LsETH contract interface.
When a redemption request is submitted by calling the requestRedeem function, a redeem request id is returned by either using the or subscribing to RequestedRedeem events.
To indicate whether the request has been satisfied, the redeem request id can be submitted along with calling the resolveRedeemRequests function to return withdrawal events corresponding to that redeem request id.
Once satisfied, the request can be claimed by calling ClaimRedeemRequests along with the redeem request id and corresponding withdrawal event id, which returns a list of claim statuses.
Interface level smart contract flow
For more technical audiences, a sequence diagram showing the interaction between smart contracts is included below:
For those that want to view a stack trace, we recommend using a tool like .
Here is a sample transaction hash on mainnet: Request Redeem: 0x996bab264e831a12618c9e942b2d30a410c62db908c16efbd9fc5e44e30b1f5c Oracle Report: 0x67d44ab16ece7c2adcc97b538359f4c21fc10a09413d7014962c5dc5b79e4cb0
Redeem status matrix
Platforms can learn more about this process in the
Redemptions and the Conversion Rate
When users request to redeem LsETH, they will receive ETH based on the available ETH from exited validators or pending deposits, up to the user's LsETH balance multiplied by the protocol conversion rate at the time of the request. If pending deposits are insufficient to fulfill the redemption request, the protocol initiates validator exits to cover the redemption. At the time of the redemption request, the protocol assumes ownership of the user’s LsETH, and the user will no longer be eligible to receive future network rewards. Once validators have fully exited and their effective balance is available, the final ETH amount is determined by the proportion of LsETH being redeemed relative to the total ETH available to withdraw. This means the user remains exposed to penalties and slashing risks until the validators have fully exited.
Example
Assuming
totalETHSupply = 162 ETH
totalLsETHSupply = 108 LsETH
So conversionRate = 162 / 108 = 1.5
Note: Figures above are just examples and do not reflect reality or projections.
Interface level smart contract flow
For more technical audiences, a sequence diagram showing the interaction between smart contracts is included below:
For those that want to view a stack trace, we recommend using a tool like .
Here is a sample transaction hash on mainnet: Request Redeem: 0xd8c39cf80d388c8ce55b519336b5f53074805156b5d416e96116c90dc73b2577 Oracle Report: 0x67d44ab16ece7c2adcc97b538359f4c21fc10a09413d7014962c5dc5b79e4cb0
Operate an Oracle
Operator running Oracle
Oracle Operators are responsible for periodically reporting consensus layer data to the Liquid Collective protocol.
In particular, they are responsible for reporting network rewards earned by validators on the consensus layer so those network rewards can be accounted for, accruing the value of the LsETH token (cToken) by increasing the Conversion Rate.
The Oracle smart contract is responsible for synchronizing Oracle Operators.
Oracle Operators
Oracle operators are responsible for periodically reporting consensus layer data to the execution layer.
In particular, they are responsible for reporting network rewards earned by validators on the consensus layer so those network rewards can be accounted for, accruing the value of the LsETH token (cToken) by increasing the Conversion Rate.
The Oracle smart contract is responsible for synchronizing Oracle operators. In particular it:
Lists the addresses of Oracle members that are expected to report
Sets the next target epoch to be reported by Oracle members
Expects a quorum of Oracle members to report the same data at the target epoch before forwarding it to the River contract
Oracle reports consist of:
The count of validators on the consensus layer
The total balance of those validators on the consensus layer
Oracle Operator Procedure
Oracle Operators interested in participating in the Oracle set should go through the following procedure:
One-Time Protocol Onboarding
Oracle Operator generates a wallet to be used as Operator members
Oracle member address gets approved on the Oracle smart contract
Oracle Daemon
Description
To facilitate operations, Oracle Operators are recommended to use the Oracle daemon which is an open-source application maintained by Liquid Collective. While the Oracle daemon is recommended, it is not mandatory, and Oracle Operators can opt-out of it and use their own preferred solution.
The Oracle daemon is a long-living application that:
Continuously listens for event logs emitted by the Operators Registry contract
Calls the Oracle contract to get the next target epoch to report
Exposes various metrics about the activity of the Oracle
When the target epoch to report is reached, it:
Collects consensus layer data for the target epoch
Generates a report from the collected data (validators count and total balance on the consensus layer)
Sends the report transaction to the Oracle contract
The Oracle daemon can optionally run in --dry-mode in which case it does not send report transactions to the chain.
Architecture
The Oracle daemon needs to be connected to:
Ethereum Execution Layer RPC endpoint
to listen for event logs emitted by the Operator registry contract (in particular events when validator keys get funded)
to aggregate all withdrawals data since the Shapella fork
The Oracle Daemon also needs access to a private key for signing report transactions. This wallet corresponds to the oracle member address that has been approved on the oracle contract.
Since the Shapella fork, it has become necessary to retrieve withdrawals for all Liquid Collective validators. However, there is no available API for this task. One solution is to read all blocks, but this consumes a large number of requests. An alternative solution is to implement a stateful approach.
As a result, we have decided to introduce a new flag in the lceth CLI, --data-dir, which stores the state of withdrawals. The stored state encompasses all withdrawals and their corresponding blocks. (The estimated size of the storage is approximately 4 GB.)
Dependencies
A synced Execution Layer client with JSON-RPC endpoint enabled. All implementations are supported (Geth, Erigon, Besu, etc.)
A synced Consensus Layer client with API endpoint enabled. All implementations are supported (Prysm, Teku, Lighthouse, etc.)
Installation
The recommended installation is to use the public Docker image public.ecr.aws/alluvial/liquid-collective/lceth:latest
It is also possible to build the binary from sources and run it.
Estimated gas cost
Sending an Oracle report uses about 100,000 gas for a regular report and ~300,000 gas when reaching the quorum.
Let's estimate how much in gas fees an Oracle Operator should pay per year, considering:
the protocol expects 1 report per day
the average gas price is 30 gwei
there are 5 oracle operators
This means that each day there is a 2/5 probability of sending a regular report and a 1/5 probability of sending a report that reaches quorum:
To generate such a wallet you can use the following command:
Once generated you should securely store the key file and password for later usage, as you will need it each time you will run the Oracle daemon.
Submit Oracle member
Submit the Oracle member address to the administrator to get it approved on the Oracle contract members list.
On-going operations
Oracle has become stateful; be sure to choose an appropriate data directory using the --data-dir flag.
Dry-Run Mode
In dry run the Oracle daemon collects data and generates reports but does not send transactions to the Oracle contract.
It is recommended to use dry run mode when:
You are not an Oracle Operator and you are only interested in collecting Oracle metrics data
You are an Oracle Operator and you want to first test in dry run before running in live mode
To run the oracle in dry-run mode, you can run:
Live Mode
In live mode, the daemon runs full capabilities and sends transactions to the chain for every epoch to be reported.
In live mode, you need the daemon to have access to the Oracle member wallet that will be used to sign report transactions.
Top up Oracle Operator account
Before starting the daemon you should make sure that the Oracle Operator account has been topped-up with ETH so it can pay for the gas fees for the report transactions.
After starting the daemon, an Oracle Operator should make sure that the Oracle member account always has a sufficient balance of ETH to send report transactions.
To run the daemon in live mode, you can run:
Oracle Daemon Command
Monitoring and Metrics
The Oracle service exposes a health endpoint that exposes routes for monitoring:
/live Liveness endpoint
/ready Readiness endpoint
/metrics
IAllowlistV1
Alluvial Finance Inc.
Allowlist Interface (v1)
This interface exposes methods to handle the list of allowed recipients.
Methods
getAllower
Retrieves the allower address
Returns
Name
Type
Description
getDenier
Retrieves the denier address
Returns
Name
Type
Description
getPermissions
This method retrieves the raw permission value
Parameters
Name
Type
Description
Returns
Name
Type
Description
hasPermission
This method returns true if the user has the expected permission ignoring any deny list membership
Parameters
Name
Type
Description
Returns
Name
Type
Description
initAllowlistV1
Initializes the allowlist
Parameters
Name
Type
Description
initAllowlistV1_1
Initializes the allowlist denier
Parameters
Name
Type
Description
isAllowed
This method returns true if the user has the expected permission and is not in the deny list
Parameters
Name
Type
Description
Returns
Name
Type
Description
isDenied
This method returns true if the user is in the deny list
Parameters
Name
Type
Description
Returns
Name
Type
Description
onlyAllowed
This method should be used as a modifier and is expected to revert if the user hasn't got the required permission or if the user is in the deny list.
Parameters
Name
Type
Description
setAllowPermissions
Sets the allow permissions for one or more accounts
This function is for allocating or removing deposit, redeem or donate permissions. This function could be used to give any permissions that we come up with in the future. An address which was denied has to be undenied first before they could be given any permission(s).
Parameters
Name
Type
Description
setAllower
Changes the allower address
Parameters
Name
Type
Description
setDenier
Changes the denier address
Parameters
Name
Type
Description
setDenyPermissions
Sets the deny permissions for one or more accounts
This function is for allocating or removing deny permissions. An address which is undenied has to be given permissions again for them to be able to deposit, donate or redeem.
Parameters
Name
Type
Description
Events
SetAllower
The stored allower address has been changed
Parameters
Name
Type
Description
SetAllowlistPermissions
The permissions of several accounts have changed
Parameters
Name
Type
Description
SetDenier
The stored denier address has been changed
Parameters
Name
Type
Description
Errors
AttemptToRemoveDenyPermission
Allower can't remove deny permission
AttemptToSetDenyPermission
Allower can't set deny permission
Denied
The account is denied access
Parameters
Name
Type
Description
InvalidCount
The provided accounts list is empty
MismatchedArrayLengths
The provided accounts and permissions list have different lengths
Withdrawn validator consensus layer ETH from validator full exits, or slashed validator exits, automatically enter the Redemption Buffer to fund LsETH redemptions
Funds from Liquid Collective’s Slashing Coverage Program enter the Deposit Buffer according to the Slashing Coverage Program to be programmatically staked
Liquid Collective Protocol
The Liquid Collective protocol’s Redemption Buffer holds ETH that is pending to be supplied for redemption satisfactions.
Deposit Buffer
Liquid Collective Protocol
The Liquid Collective protocol’s Deposit Buffer holds ETH pending to be deposited to Ethereum’s consensus layer, or that can be rebalanced to the Withdrawal Stack to programmatically facilitate redemption satisfactions. This ETH may be sourced from user deposits, network rewards (consensus layer & execution layer), the protocol’s Slashing Coverage Program, or rebalanced from the protocol’s Withdrawal Stack.
A user deposits 10 ETH and receives 10 / 1.25 = 8 LsETH
And the new conversionRate = (125+10) / (100+8) = 1.25 remains unchanged
If the balance in the Deposit Buffer is insufficient to satisfy all pending redemption requests the Liquid Collective protocol initiates the exit of a corresponding amount of ETH by programmatically requesting Node Operators to submit validator exits
Any redemption request that has been satisfied by the Buffer can be immediately claimed by the user
For redemption requests that require a validator exit to satisfy, the validator key enters Ethereum’s exit queue, waits the full network withdrawal time, and, once exited, the validator’s ETH balance is automatically sent by Ethereum to Liquid Collective’s withdrawal address
On the Oracle report following the validator exit, the withdrawn ETH satisfies pending redemption requests
The user can now claim their ETH
PARTIALLY_CLAIMED
Request was partially claimed and is pending satisfaction for the remaining part. The request can not be claimed yet.
FULLY_SATISFIED
PARTIALLY_CLAIMED
Request was partially claimed and is now fully satisfied so can be claimed again to collect the remaining part.
PARTIALLY_SATISFIED
PARTIALLY_CLAIMED
Request was partially claimed and is now partially satisfied, thus can be partially claimed and will require another claim later.
A user converts 8 LsETH and receives 8 * 1.5 = 12 ETH
And the new conversionRate = (162-12) / (108-8) = 1.5 remains unchanged
Name
Owner
Role
Activation Queue
Ethereum Consensus Protocol
Ethereum’s Activation Queue rate limits the number of new validators that can be activated on the network to protect the network’s stability. The Activation Queue can result in a waiting time to activate stake on Ethereum. Learn more here.
Exit Queue
Ethereum Consensus Protocol
Ethereum’s Exit Queue rate limits the speed at which validators can leave the network to protect the network’s stability, and to ensure that slashing penalties are applied as necessary. The Exit Queue can result in a waiting time to withdraw stake from Ethereum. Learn more here.
Redemption Queue
Liquid Collective Protocol
The Liquid Collective protocol’s Redemption Queue facilitates the satisfaction of redemption requests in the same order as they have been requested. The first-in-first-out Redemption Queue is intended to protect against a race for claims in the event of high withdrawal demand.
Withdrawal Stack
Liquid Collective Protocol
The Liquid Collective protocol’s Withdrawal Stack automatically facilitates the movement of ETH to the protocol’s Redemption Buffer. This ETH may be sourced by validator exits from the consensus layer or rebalanced from the protocol’s Deposit Buffer.
Status Satisfaction
Status Claim
Meaning
PENDING_SATISFACTION
NOT_CLAIMED
Redeem is in process of being satisfied and cannot be claimed yet.
FULLY_SATISFIED
NOT_CLAIMED
Redeem request is fully satisfied thus can be claimed.
FULLY_SATISFIED
FULLY_CLAIMED
Redeem was fully claimed after getting fully satisfied. All funds have been sent to the recipient and redeem can not be claimed again.
PARTIALLY_SATISFIED
NOT_CLAIMED
Redeem request is partially satisfied and thus can be partially claimed and will require to claim again later on. User may decide to either a) claim now to receive part of the funds and proceed with other claim(s) later on, or b) wait for the request to be FULLY_SATISFIED so that only a single claim is required.
env ETH_EL_ADDR={ethereum execution layer rpc endpoint} \
ETH_CL_ADDR={ethereum consensus layer endpoint} \
KEYSTORE_PASSWORD={password used to encrypt the Oracle member key file} \
ORACLE_MEMBER_ADDR={address of the Oracle member wallet} \
ORACLE_DATA_DIR="/data" \
lceth oracle run
docker run \
-e ETH_EL_ADDR={ethereum execution layer rpc endpoint}
-e ETH_CL_ADDR={ethereum consensus layer endpoint} \
-e ORACLE_DATA_DIR="/data" \
-e KEYSTORE_PASSWORD={password used to encrypt the Oracle member key file} \
-e ORACLE_MEMBER_ADDR={address of the Oracle member wallet} \
-v "data:/data" \
-v "keystore:/keystore" \
public.ecr.aws/alluvial/liquid-collective/lceth \
oracle run
Run Oracle reporter deamon
Usage:
lceth oracle run [flags]
Flags:
--eth-cl-addr string Address of the Ethereum consensus layer node to connect to [env: ETH_CL_ADDR]
--dry-run Run oracle reporter without attempting to submit on-chain reports [env: ORACLE_DRY_RUN]
--gas-limit int Set gas limit when submitting reports [env: ORACLE_GAS_LIMIT] (default 600000)
--member-addr string Ethereum address of the oracle operator used to sign and submit reports [env: ORACLE_MEMBER_ADDR]
--report-distance int Maximum count of epochs after frame start where oracle has to report [env: ORACLE_REPORT_DISTANCE]
--withdrawal-batch-size int Maximum count of withdrawals blocks to fetch in parallel [env: ORACLE_WITHDRAWAL_BATCH_SIZE] (default 20)
--data-dir string Local directory where to store withdrawal data [env: ORACLE_DATA_DIR] (default "./data")
--loop-sleep-time duration Duration in seconds between 2 fetch calls [env: ORACLE_LOOP_SLEEP_TIME] (default 15s)
-h, --help help for run
Global Flags:
--allowlist-addr string Address of the Allowlist contract [env: ALLOWLIST_ADDR]
--deployment-block uint Deployment block of the contracts [env: DEPLOYMENT_BLOCK]
--el-fee-recipient-addr string Address of the Execution Layer fee recipient contract [env: EL_FEE_RECIPIENT_ADDR]
--eth-el-addr string JSON-RPC address of the Ethereum execution layer node to connect to [env: ETH_EL_ADDR]
--keystore-password string Password used to encrypt key files [env: KEYSTORE_PASSWORD]
--keystore-path string Directory where to store keys [env: KEYSTORE_PATH]
--log-format string Log output format (text or json) [env: LOG_FORMAT] (default "text")
--log-level string Log output level [env: LOG_LEVEL] (default "info")
--operators-registry-addr string Address of the Operators Registry contract [env: OPERATORS_REGISTRY_ADDR]
--oracle-addr string Address of the Oracle contract [env: ORACLE_ADDR]
--redeem-manager-addr string Address of the RedeemManager contract [env: REDEEM_MANAGER_ADDR]
--river-addr string Address of the River contract [env: RIVER_ADDR]
--tlc-addr string Address of the TLC contract [env: TLC_ADDR]
--withdraw-addr string Address of the Withdraw contract [env: WITHDRAW_ADDR]
--wls-eth-addr string Address of the WlsEth contract [env: WLSETH_ADDR]
function getAllower() external view returns (address)
function getDenier() external view returns (address)
function getPermissions(address _account) external view returns (uint256)
function hasPermission(address _account, uint256 _mask) external view returns (bool)
function initAllowlistV1(address _admin, address _allower) external nonpayable
function initAllowlistV1_1(address _denier) external nonpayable
function isAllowed(address _account, uint256 _mask) external view returns (bool)
function isDenied(address _account) external view returns (bool)
function onlyAllowed(address _account, uint256 _mask) external view
function setAllowPermissions(address[] _accounts, uint256[] _permissions) external nonpayable
function setAllower(address _newAllowerAddress) external nonpayable
function setDenier(address _newDenierAddress) external nonpayable
function setDenyPermissions(address[] _accounts, uint256[] _permissions) external nonpayable
Computes the releasable amount of tokens for a vesting schedule.
Parameters
Name
Type
Description
Returns
Name
Type
Description
computeVestingVestedAmount
Computes the vested amount of tokens for a vesting schedule.
Parameters
Name
Type
Description
Returns
Name
Type
Description
createVestingSchedule
Creates a new vesting scheduleThere may delay between the time a user should start vesting tokens and the time the vesting schedule is actually created on the contract.Typically a user joins the Liquid Collective but some weeks pass before the user gets all legal agreements in place and signed for the token grant emission to happen. In this case, the vesting schedule created for the token grant would start on the join date which is in the past.
As vesting schedules can be created in the past, this means that you should be careful when creating a vesting schedule and what duration parameters you use as this contract would allow creating a vesting schedule in the past and even a vesting schedule that has already ended.
Parameters
Name
Type
Description
Returns
Name
Type
Description
delegateVestingEscrow
Delegate vesting escrowed tokens
Parameters
Name
Type
Description
Returns
Name
Type
Description
getVestingSchedule
Get vesting schedule
The vesting schedule structure represents a static configuration used to compute the desired vesting details of a beneficiary at all times. The values won't change even after tokens are released.The only dynamic field of the structure is end, and is updated whenever a vesting schedule is revoked
Parameters
Name
Type
Description
Returns
Name
Type
Description
getVestingScheduleCount
Get count of vesting schedules
Returns
Name
Type
Description
isGlobalUnlockedScheduleIgnored
Get vesting global unlock schedule activation status for a vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
releaseVestingSchedule
Release vesting scheduleWhen tokens are released from the escrow, the delegated address of the escrow will see its voting power decrease.The beneficiary has to make sure its delegation parameters are set properly to be able to use/delegate the voting power of its balance.
Parameters
Name
Type
Description
Returns
Name
Type
Description
revokeVestingSchedule
Revoke vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
vestingEscrow
Get the address of the escrow for a vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
CreatedVestingSchedule
A new vesting schedule has been created
Parameters
Name
Type
Description
DelegatedVestingEscrow
Vesting escrow has been delegated
Parameters
Name
Type
Description
ReleasedVestingSchedule
Vesting schedule has been released
Parameters
Name
Type
Description
RevokedVestingSchedule
Vesting schedule has been revoked
Parameters
Name
Type
Description
Errors
GlobalUnlockUnderlfow
Underflow in global unlock logic (should never happen)
InvalidRevokedVestingScheduleEnd
Attempt to revoke a vesting schedule with an invalid end parameter
InvalidVestingScheduleParameter
Invalid parameter for a vesting schedule
Parameters
Name
Type
Description
UnsufficientVestingScheduleCreatorBalance
Vesting schedule creator has unsufficient balance to create vesting schedule
VestingScheduleIsLocked
The vesting schedule is locked
VestingScheduleNotRevocable
The vesting schedule is not revocable
VestingScheduleNotRevocableInPast
Attempt to revoke a schedule in the past
ZeroReleasableAmount
No token to release
IOracleManagerV1
Alluvial Finance Inc.
Oracle Manager (v1)
This interface exposes methods to handle the inputs provided by the oracle
Methods
_lockDuration
uint32
duration during which tokens are locked (in seconds)
_revocable
bool
whether the vesting schedule is revocable or not
_amount
uint256
amount of token attributed by the vesting schedule
_beneficiary
address
address of the beneficiary of the tokens
_delegatee
address
address to delegate escrow voting power to
_ignoreGlobalUnlockSchedule
bool
whether the vesting schedule should ignore the global lock
_index
uint256
index of the vesting schedule
_0
uint256
amount of releasable tokens
_index
uint256
index of the vesting schedule
_0
uint256
amount of vested tokens
_start
uint64
start time of the vesting
_cliffDuration
uint32
duration to vesting cliff (in seconds)
_duration
uint32
total vesting schedule duration after which all tokens are vested (in seconds)
_periodDuration
uint32
_0
uint256
index of the created vesting schedule
_index
uint256
index of the vesting schedule
_delegatee
address
address to delegate the token to
_0
bool
True on success
_index
uint256
Index of the vesting schedule
_0
VestingSchedulesV2.VestingSchedule
undefined
_0
uint256
count of vesting schedules
_index
uint256
Index of the vesting schedule
_0
bool
true if the vesting schedule should ignore the global unlock schedule
_index
uint256
Index of the vesting schedule to release
_0
uint256
released amount
_index
uint256
Index of the vesting schedule to revoke
_end
uint64
End date for the schedule
returnedAmount
uint256
amount returned to the vesting schedule creator
_index
uint256
Index of the vesting schedule
_0
address
address of the escrow
index
uint256
Vesting schedule index
creator indexed
address
Creator of the vesting schedule
beneficiary indexed
address
Vesting beneficiary address
amount
uint256
index
uint256
Vesting schedule index
oldDelegatee indexed
address
old delegatee
newDelegatee indexed
address
new delegatee
beneficiary indexed
address
index
uint256
Vesting schedule index
releasedAmount
uint256
Amount of tokens released to the beneficiary
index
uint256
Vesting schedule index
returnedAmount
uint256
Amount of tokens returned to the creator
newEnd
uint256
New end timestamp after revoke action
msg
string
undefined
duration of a period after which new tokens unlock (in seconds)
Vesting schedule amount
vesting schedule beneficiary
function computeVestingReleasableAmount(uint256 _index) external view returns (uint256)
function computeVestingVestedAmount(uint256 _index) external view returns (uint256)
Get CL validator count (the amount of validator reported by the oracles)
Returns
Name
Type
Description
_0
uint256
The CL validator count
getCLValidatorTotalBalance
Get CL validator total balance
Returns
Name
Type
Description
_0
uint256
The CL Validator total balance
getCurrentEpochId
Retrieve the current epoch id based on block timestamp
Returns
Name
Type
Description
_0
uint256
The current epoch id
getCurrentFrame
Retrieve the current frame details
Returns
Name
Type
Description
_startEpochId
uint256
The epoch at the beginning of the frame
_startTime
uint256
The timestamp of the beginning of the frame in seconds
_endTime
uint256
The timestamp of the end of the frame in seconds
getExpectedEpochId
Retrieve expected epoch id
Returns
Name
Type
Description
_0
uint256
The current expected epoch id
getFrameFirstEpochId
Retrieve the first epoch id of the frame of the provided epoch id
Parameters
Name
Type
Description
_epochId
uint256
Epoch id used to get the frame
Returns
Name
Type
Description
_0
uint256
The first epoch id of the frame containing the given epoch id
getLastCompletedEpochId
Retrieve the last completed epoch id
Returns
Name
Type
Description
_0
uint256
The last completed epoch id
getLastConsensusLayerReport
Retrieve the last consensus layer report
Returns
Name
Type
Description
_0
IOracleManagerV1.StoredConsensusLayerReport
The stored consensus layer report
getOracle
Get oracle address
Returns
Name
Type
Description
_0
address
The oracle address
getReportBounds
Retrieve the report bounds
Returns
Name
Type
Description
_0
ReportBounds.ReportBoundsStruct
The report bounds
getTime
Retrieve the block timestamp
Returns
Name
Type
Description
_0
uint256
The current timestamp from the EVM context
isValidEpoch
Verifies if the provided epoch is valid
Parameters
Name
Type
Description
epoch
uint256
The epoch to lookup
Returns
Name
Type
Description
_0
bool
True if valid
setCLSpec
Parameters
Name
Type
Description
_newValue
CLSpec.CLSpecStruct
undefined
setConsensusLayerData
Parameters
Name
Type
Description
_report
IOracleManagerV1.ConsensusLayerReport
undefined
setOracle
Set the oracle address
Parameters
Name
Type
Description
_oracleAddress
address
Address of the oracle
setReportBounds
Parameters
Name
Type
Description
_newValue
ReportBounds.ReportBoundsStruct
undefined
Events
ConsensusLayerDataUpdate
The consensus layer data provided by the oracle has been updated
Parameters
Name
Type
Description
validatorCount
uint256
The new count of validators running on the consensus layer
validatorTotalBalance
uint256
The new total balance sum of all validators
roundId
bytes32
Round identifier
ProcessedConsensusLayerReport
The provided report has been processed
Parameters
Name
Type
Description
report
IOracleManagerV1.ConsensusLayerReport
The report that was provided
trace
IOracleManagerV1.ConsensusLayerDataReportingTrace
The trace structure providing more insights on internals
SetBounds
The Report Bounds are changed
Parameters
Name
Type
Description
annualAprUpperBound
uint256
The reporting upper bound
relativeLowerBound
uint256
The reporting lower bound
SetOracle
The stored oracle address changed
Parameters
Name
Type
Description
oracleAddress indexed
address
The new oracle address
SetSpec
The Consensus Layer Spec is changed
Parameters
Name
Type
Description
epochsPerFrame
uint64
The number of epochs inside a frame
slotsPerEpoch
uint64
The number of slots inside an epoch
secondsPerSlot
uint64
The number of seconds inside a slot
genesisTime
uint64
Errors
InvalidDecreasingValidatorsExitedBalance
The total exited balance decreased
Parameters
Name
Type
Description
currentValidatorsExitedBalance
uint256
The current exited balance
newValidatorsExitedBalance
uint256
The new exited balance
InvalidDecreasingValidatorsSkimmedBalance
The total skimmed balance decreased
Parameters
Name
Type
Description
currentValidatorsSkimmedBalance
uint256
The current exited balance
newValidatorsSkimmedBalance
uint256
The new exited balance
InvalidEpoch
Thrown when an invalid epoch was reported
Parameters
Name
Type
Description
epoch
uint256
Invalid epoch
InvalidValidatorCountReport
The reported validator count is invalid
Parameters
Name
Type
Description
providedValidatorCount
uint256
The received validator count value
depositedValidatorCount
uint256
The number of deposits performed by the system
lastReportedValidatorCount
uint256
The last reported validator count
TotalValidatorBalanceDecreaseOutOfBound
The balance decrease is higher than the maximum allowed by the lower bound
Parameters
Name
Type
Description
prevTotalEthIncludingExited
uint256
The previous total balance, including all exited balance
postTotalEthIncludingExited
uint256
The post-report total balance, including all exited balance
timeElapsed
uint256
The time in seconds since last report
relativeLowerBound
uint256
The lower bound value that was used
TotalValidatorBalanceIncreaseOutOfBound
The balance increase is higher than the maximum allowed by the upper bound
Parameters
Name
Type
Description
prevTotalEthIncludingExited
uint256
The previous total balance, including all exited balance
postTotalEthIncludingExited
uint256
The post-report total balance, including all exited balance
timeElapsed
uint256
The time in seconds since last report
annualAprUpperBound
uint256
AllowlistV1
Alluvial Finance Inc.
Allowlist (v1)
This contract handles the list of allowed recipients.All accounts have an uint256 value associated with their addresses where each bit represents a right in the system. The DENY_MASK defined the mask used to identify if the denied bit is on, preventing users from interacting with the system
Methods
acceptAdmin
Accept the transfer of ownership
Only callable by the pending admin. Resets the pending admin if successful.
getAdmin
Retrieves the current admin address
Returns
Name
Type
Description
getAllower
Retrieves the allower address
Returns
Name
Type
Description
getDenier
Retrieves the denier address
Returns
Name
Type
Description
getPendingAdmin
Retrieve the current pending admin address
Returns
Name
Type
Description
getPermissions
This method retrieves the raw permission value
Parameters
Name
Type
Description
Returns
Name
Type
Description
hasPermission
This method returns true if the user has the expected permission ignoring any deny list membership
Parameters
Name
Type
Description
Returns
Name
Type
Description
initAllowlistV1
Initializes the allowlist
Parameters
Name
Type
Description
initAllowlistV1_1
Initializes the allowlist denier
Parameters
Name
Type
Description
isAllowed
This method returns true if the user has the expected permission and is not in the deny list
Parameters
Name
Type
Description
Returns
Name
Type
Description
isDenied
This method returns true if the user is in the deny list
Parameters
Name
Type
Description
Returns
Name
Type
Description
onlyAllowed
This method should be used as a modifier and is expected to revert if the user hasn't got the required permission or if the user is in the deny list.
Parameters
Name
Type
Description
proposeAdmin
Proposes a new address as admin
This security prevents setting an invalid address as an admin. The pending admin has to claim its ownership of the contract, and prove that the new address is able to perform regular transactions.
Parameters
Name
Type
Description
setAllowPermissions
Sets the allow permissions for one or more accounts
This function is for allocating or removing deposit, redeem or donate permissions. This function could be used to give any permissions that we come up with in the future. An address which was denied has to be undenied first before they could be given any permission(s).
Parameters
Name
Type
Description
setAllower
Changes the allower address
Parameters
Name
Type
Description
setDenier
Changes the denier address
Parameters
Name
Type
Description
setDenyPermissions
Sets the deny permissions for one or more accounts
This function is for allocating or removing deny permissions. An address which is undenied has to be given permissions again for them to be able to deposit, donate or redeem.
Parameters
Name
Type
Description
version
Retrieves the version of the contract
Returns
Name
Type
Description
Events
Initialize
Emitted when the contract is properly initialized
Parameters
Name
Type
Description
SetAdmin
The admin address changed
Parameters
Name
Type
Description
SetAllower
The stored allower address has been changed
Parameters
Name
Type
Description
SetAllowlistPermissions
The permissions of several accounts have changed
Parameters
Name
Type
Description
SetDenier
The stored denier address has been changed
Parameters
Name
Type
Description
SetPendingAdmin
The pending admin address changed
Parameters
Name
Type
Description
Errors
AttemptToRemoveDenyPermission
Allower can't remove deny permission
AttemptToSetDenyPermission
Allower can't set deny permission
Denied
The account is denied access
Parameters
Name
Type
Description
InvalidCount
The provided accounts list is empty
InvalidInitialization
An error occurred during the initialization
Parameters
Name
Type
Description
InvalidZeroAddress
The address is zero
MismatchedArrayLengths
The provided accounts and permissions list have different lengths
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
SharesManagerV1
Alluvial Finance Inc.
Shares Manager (v1)
This contract handles the shares of the depositor and the ERC20 interface
Methods
allowance
Retrieve the allowance value for a spender
Parameters
Name
Type
Description
Returns
Name
Type
Description
approve
Approves an account for future spendings
An approved account can use transferFrom to transfer funds on behalf of the token owner
Parameters
Name
Type
Description
Returns
Name
Type
Description
balanceOf
Retrieve the balance of an account
Parameters
Name
Type
Description
Returns
Name
Type
Description
balanceOfUnderlying
Retrieve the underlying asset balance of an account
Parameters
Name
Type
Description
Returns
Name
Type
Description
decimals
Retrieve the decimal count
Returns
Name
Type
Description
decreaseAllowance
Decrease allowance to another account
Parameters
Name
Type
Description
Returns
Name
Type
Description
increaseAllowance
Increase allowance to another account
Parameters
Name
Type
Description
Returns
Name
Type
Description
name
Retrieve the token name
Returns
Name
Type
Description
sharesFromUnderlyingBalance
Retrieve the shares count from an underlying asset amount
Parameters
Name
Type
Description
Returns
Name
Type
Description
symbol
Retrieve the token symbol
Returns
Name
Type
Description
totalSupply
Retrieve the total token supply
Returns
Name
Type
Description
totalUnderlyingSupply
Retrieve the total underlying asset supply
Returns
Name
Type
Description
transfer
Performs a transfer from the message sender to the provided account
Parameters
Name
Type
Description
Returns
Name
Type
Description
transferFrom
Performs a transfer between two recipients
Parameters
Name
Type
Description
Returns
Name
Type
Description
underlyingBalanceFromShares
Retrieve the underlying asset balance from an amount of shares
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
Approval
Emitted when the allowance of a spender for an owner is set by a call to {approve}. value is the new allowance.
Parameters
Name
Type
Description
SetTotalSupply
Emitted when the total supply is changed
Parameters
Name
Type
Description
Transfer
Emitted when value tokens are moved from one account (from) to another (to). Note that value may be zero.
Parameters
Name
Type
Description
Errors
AllowanceTooLow
Allowance too low to perform operation
Parameters
Name
Type
Description
BalanceTooLow
Balance too low to perform operation
InvalidZeroAddress
The address is zero
NullTransfer
Invalid empty transfer
UnauthorizedTransfer
Invalid transfer recipients
Parameters
Name
Type
Description
OracleManagerV1
Alluvial Finance Inc.
Oracle Manager (v1)
This contract handles the inputs provided by the oracle. The Oracle contract is plugged to this contract and is in charge of pushing data whenever a new report has been deemed valid. The report consists in two values: the sum of all balances of all deposited validators and the count of validators that have been activated on the consensus layer.
Methods
_DEPOSIT_SIZE
Size of a deposit in ETH
Returns
Name
Type
Description
getCLSpec
Retrieve the current cl spec
Returns
Name
Type
Description
getCLValidatorCount
Get CL validator count (the amount of validator reported by the oracles)
Returns
Name
Type
Description
getCLValidatorTotalBalance
Get CL validator total balance
Returns
Name
Type
Description
getCurrentEpochId
Retrieve the current epoch id based on block timestamp
Returns
Name
Type
Description
getCurrentFrame
Retrieve the current frame details
Returns
Name
Type
Description
getExpectedEpochId
Retrieve expected epoch id
Returns
Name
Type
Description
getFrameFirstEpochId
Retrieve the first epoch id of the frame of the provided epoch id
Parameters
Name
Type
Description
Returns
Name
Type
Description
getLastCompletedEpochId
Retrieve the last completed epoch id
Returns
Name
Type
Description
getLastConsensusLayerReport
Retrieve the last consensus layer report
Returns
Name
Type
Description
getOracle
Get oracle address
Returns
Name
Type
Description
getReportBounds
Retrieve the report bounds
Returns
Name
Type
Description
getTime
Retrieve the block timestamp
Returns
Name
Type
Description
isValidEpoch
Verifies if the provided epoch is valid
Parameters
Name
Type
Description
Returns
Name
Type
Description
setCLSpec
Parameters
Name
Type
Description
setConsensusLayerData
Parameters
Name
Type
Description
setOracle
Set the oracle address
Parameters
Name
Type
Description
setReportBounds
Parameters
Name
Type
Description
Events
ConsensusLayerDataUpdate
The consensus layer data provided by the oracle has been updated
Parameters
Name
Type
Description
ProcessedConsensusLayerReport
The provided report has been processed
Parameters
Name
Type
Description
SetBounds
The Report Bounds are changed
Parameters
Name
Type
Description
SetOracle
The stored oracle address changed
Parameters
Name
Type
Description
SetSpec
The Consensus Layer Spec is changed
Parameters
Name
Type
Description
Errors
InvalidDecreasingValidatorsExitedBalance
The total exited balance decreased
Parameters
Name
Type
Description
InvalidDecreasingValidatorsSkimmedBalance
The total skimmed balance decreased
Parameters
Name
Type
Description
InvalidEpoch
Thrown when an invalid epoch was reported
Parameters
Name
Type
Description
InvalidValidatorCountReport
The reported validator count is invalid
Parameters
Name
Type
Description
InvalidZeroAddress
The address is zero
TotalValidatorBalanceDecreaseOutOfBound
The balance decrease is higher than the maximum allowed by the lower bound
Parameters
Name
Type
Description
TotalValidatorBalanceIncreaseOutOfBound
The balance increase is higher than the maximum allowed by the upper bound
Parameters
Name
Type
Description
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
ISharesManagerV1
Alluvial Finance Inc.
Shares Manager Interface (v1)
This interface exposes methods to handle the shares of the depositor and the ERC20 interface
Methods
allowance
Retrieve the allowance value for a spender
Parameters
Name
Type
Description
Returns
Name
Type
Description
approve
Approves an account for future spendings
An approved account can use transferFrom to transfer funds on behalf of the token owner
Parameters
Name
Type
Description
Returns
Name
Type
Description
balanceOf
Retrieve the balance of an account
Parameters
Name
Type
Description
Returns
Name
Type
Description
balanceOfUnderlying
Retrieve the underlying asset balance of an account
Parameters
Name
Type
Description
Returns
Name
Type
Description
decimals
Retrieve the decimal count
Returns
Name
Type
Description
decreaseAllowance
Decrease allowance to another account
Parameters
Name
Type
Description
Returns
Name
Type
Description
increaseAllowance
Increase allowance to another account
Parameters
Name
Type
Description
Returns
Name
Type
Description
name
Retrieve the token name
Returns
Name
Type
Description
sharesFromUnderlyingBalance
Retrieve the shares count from an underlying asset amount
Parameters
Name
Type
Description
Returns
Name
Type
Description
symbol
Retrieve the token symbol
Returns
Name
Type
Description
totalSupply
Retrieve the total token supply
Returns
Name
Type
Description
totalUnderlyingSupply
Retrieve the total underlying asset supply
Returns
Name
Type
Description
transfer
Performs a transfer from the message sender to the provided account
Parameters
Name
Type
Description
Returns
Name
Type
Description
transferFrom
Performs a transfer between two recipients
Parameters
Name
Type
Description
Returns
Name
Type
Description
underlyingBalanceFromShares
Retrieve the underlying asset balance from an amount of shares
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
Approval
Emitted when the allowance of a spender for an owner is set by a call to {approve}. value is the new allowance.
Parameters
Name
Type
Description
SetTotalSupply
Emitted when the total supply is changed
Parameters
Name
Type
Description
Transfer
Emitted when value tokens are moved from one account (from) to another (to). Note that value may be zero.
Parameters
Name
Type
Description
Errors
AllowanceTooLow
Allowance too low to perform operation
Parameters
Name
Type
Description
BalanceTooLow
Balance too low to perform operation
NullTransfer
Invalid empty transfer
UnauthorizedTransfer
Invalid transfer recipients
Parameters
Name
Type
Description
WLSETHV1
Alluvial Finance Inc.
Wrapped LsETH (v1)
This contract wraps the LsETH token into a rebase token, more suitable for some DeFi use-cases like stable swaps.
Methods
IWLSETHV1
Alluvial Finance Inc.
Wrapped LsETH Interface (v1)
This interface exposes methods to wrap the LsETH token into a rebase token.
Methods
function getCLSpec() external view returns (struct CLSpec.CLSpecStruct)
function getCLValidatorCount() external view returns (uint256)
function getCLValidatorTotalBalance() external view returns (uint256)
function getCurrentEpochId() external view returns (uint256)
Retrieves the token allowance given from one address to another
Parameters
Name
Type
Description
_owner
address
Owner that gave the allowance
_spender
address
Spender that received the allowance
Returns
Name
Type
Description
_0
uint256
The allowance of the owner to the spender
approve
Approves another account to transfer tokens
Parameters
Name
Type
Description
_spender
address
Spender that receives the allowance
_value
uint256
Amount to allow
Returns
Name
Type
Description
_0
bool
True if success
balanceOf
Retrieves the token balance of the specified user
Parameters
Name
Type
Description
_owner
address
Owner to check the balance
Returns
Name
Type
Description
_0
uint256
The balance of the owner
burn
Burn tokens and retrieve underlying LsETH tokens
The message sender burns shares from its balance for the LsETH equivalent valueThe message sender doesn't need to approve the contract to burn the sharesThe freed LsETH is sent to the specified recipient
Parameters
Name
Type
Description
_recipient
address
The account receiving the underlying LsETH tokens after shares are burned
_shares
uint256
Amount of LsETH to free by burning wrapped LsETH
decimals
Retrieves the token decimal count
Returns
Name
Type
Description
_0
uint8
The decimal count
decreaseAllowance
Decrease allowance to another account
Parameters
Name
Type
Description
_spender
address
Spender that receives the allowance
_subtractableValue
uint256
Amount to subtract
Returns
Name
Type
Description
_0
bool
True if success
increaseAllowance
Increase allowance to another account
Parameters
Name
Type
Description
_spender
address
Spender that receives the allowance
_additionalValue
uint256
Amount to add
Returns
Name
Type
Description
_0
bool
True if success
initWLSETHV1
Initializes the wrapped token contract
Parameters
Name
Type
Description
_river
address
Address of the River contract
mint
Mint tokens by providing LsETH tokens
The message sender locks LsETH tokens and received wrapped LsETH tokens in exchangeThe message sender needs to approve the contract to mint the wrapped tokensThe minted wrapped LsETH is sent to the specified recipient
Parameters
Name
Type
Description
_recipient
address
The account receiving the new minted wrapped LsETH
_shares
uint256
The amount of LsETH to wrap
name
Retrieves the token full name
Returns
Name
Type
Description
_0
string
The name of the token
sharesOf
Retrieves the raw shares count of the user
Parameters
Name
Type
Description
_owner
address
Owner to check the shares balance
Returns
Name
Type
Description
_0
uint256
The shares of the owner
symbol
Retrieves the token symbol
Returns
Name
Type
Description
_0
string
The symbol of the token
totalSupply
Retrieves the token total supply
Returns
Name
Type
Description
_0
uint256
The total supply
transfer
Transfers tokens between the message sender and a recipient
Parameters
Name
Type
Description
_to
address
Recipient of the transfer
_value
uint256
Amount to transfer
Returns
Name
Type
Description
_0
bool
True if success
transferFrom
Transfers tokens between two accounts
It is expected that _from has given at least _value allowance to msg.sender
Parameters
Name
Type
Description
_from
address
Sender account
_to
address
Recipient of the transfer
_value
uint256
Amount to transfer
Returns
Name
Type
Description
_0
bool
True if success
Events
Approval
An approval has been made
Parameters
Name
Type
Description
owner indexed
address
The token owner
spender indexed
address
The account allowed by the owner
value
uint256
The amount allowed
Burn
Tokens have been burned
Parameters
Name
Type
Description
recipient indexed
address
The account that receive the underlying LsETH
shares
uint256
The amount of LsETH that got sent back
Initialized
Triggered when the contract has been initialized or reinitialized.
Parameters
Name
Type
Description
version
uint8
undefined
Mint
Tokens have been minted
Parameters
Name
Type
Description
recipient indexed
address
The account receiving the new tokens
shares
uint256
The amount of LsETH provided
SetRiver
The stored value of river has been changed
Parameters
Name
Type
Description
river indexed
address
The new address of river
Transfer
A transfer has been made
Parameters
Name
Type
Description
from indexed
address
The transfer sender
to indexed
address
The transfer recipient
value
uint256
The amount transferred
Errors
AllowanceTooLow
Allowance too low to perform operation
Parameters
Name
Type
Description
_from
address
Account where funds are sent from
_operator
address
Account attempting the transfer
_allowance
uint256
Current allowance
_value
uint256
BalanceTooLow
Balance too low to perform operation
InvalidZeroAddress
The address is zero
NullTransfer
Invalid empty transfer
TokenTransferError
The token transfer failed during the minting or burning process
UnauthorizedTransfer
Invalid transfer recipients
Parameters
Name
Type
Description
_from
address
Account sending the funds in the invalid transfer
_to
address
Account receiving the funds in the invalid transfer
allowance
Retrieves the token allowance given from one address to another
Parameters
Name
Type
Description
_owner
address
Owner that gave the allowance
_spender
address
Spender that received the allowance
Returns
Name
Type
Description
_0
uint256
The allowance of the owner to the spender
approve
Approves another account to transfer tokens
Parameters
Name
Type
Description
_spender
address
Spender that receives the allowance
_value
uint256
Amount to allow
Returns
Name
Type
Description
_0
bool
True if success
balanceOf
Retrieves the token balance of the specified user
Parameters
Name
Type
Description
_owner
address
Owner to check the balance
Returns
Name
Type
Description
_0
uint256
The balance of the owner
burn
Burn tokens and retrieve underlying LsETH tokens
The message sender burns shares from its balance for the LsETH equivalent valueThe message sender doesn't need to approve the contract to burn the sharesThe freed LsETH is sent to the specified recipient
Parameters
Name
Type
Description
_recipient
address
The account receiving the underlying LsETH tokens after shares are burned
_shares
uint256
Amount of LsETH to free by burning wrapped LsETH
decimals
Retrieves the token decimal count
Returns
Name
Type
Description
_0
uint8
The decimal count
decreaseAllowance
Decrease allowance to another account
Parameters
Name
Type
Description
_spender
address
Spender that receives the allowance
_subtractableValue
uint256
Amount to subtract
Returns
Name
Type
Description
_0
bool
True if success
increaseAllowance
Increase allowance to another account
Parameters
Name
Type
Description
_spender
address
Spender that receives the allowance
_additionalValue
uint256
Amount to add
Returns
Name
Type
Description
_0
bool
True if success
initWLSETHV1
Initializes the wrapped token contract
Parameters
Name
Type
Description
_river
address
Address of the River contract
mint
Mint tokens by providing LsETH tokens
The message sender locks LsETH tokens and received wrapped LsETH tokens in exchangeThe message sender needs to approve the contract to mint the wrapped tokensThe minted wrapped LsETH is sent to the specified recipient
Parameters
Name
Type
Description
_recipient
address
The account receiving the new minted wrapped LsETH
_shares
uint256
The amount of LsETH to wrap
name
Retrieves the token full name
Returns
Name
Type
Description
_0
string
The name of the token
sharesOf
Retrieves the raw shares count of the user
Parameters
Name
Type
Description
_owner
address
Owner to check the shares balance
Returns
Name
Type
Description
_0
uint256
The shares of the owner
symbol
Retrieves the token symbol
Returns
Name
Type
Description
_0
string
The symbol of the token
totalSupply
Retrieves the token total supply
Returns
Name
Type
Description
_0
uint256
The total supply
transfer
Transfers tokens between the message sender and a recipient
Parameters
Name
Type
Description
_to
address
Recipient of the transfer
_value
uint256
Amount to transfer
Returns
Name
Type
Description
_0
bool
True if success
transferFrom
Transfers tokens between two accounts
It is expected that _from has given at least _value allowance to msg.sender
Parameters
Name
Type
Description
_from
address
Sender account
_to
address
Recipient of the transfer
_value
uint256
Amount to transfer
Returns
Name
Type
Description
_0
bool
True if success
Events
Approval
An approval has been made
Parameters
Name
Type
Description
owner indexed
address
The token owner
spender indexed
address
The account allowed by the owner
value
uint256
The amount allowed
Burn
Tokens have been burned
Parameters
Name
Type
Description
recipient indexed
address
The account that receive the underlying LsETH
shares
uint256
The amount of LsETH that got sent back
Mint
Tokens have been minted
Parameters
Name
Type
Description
recipient indexed
address
The account receiving the new tokens
shares
uint256
The amount of LsETH provided
SetRiver
The stored value of river has been changed
Parameters
Name
Type
Description
river indexed
address
The new address of river
Transfer
A transfer has been made
Parameters
Name
Type
Description
from indexed
address
The transfer sender
to indexed
address
The transfer recipient
value
uint256
The amount transferred
Errors
AllowanceTooLow
Allowance too low to perform operation
Parameters
Name
Type
Description
_from
address
Account where funds are sent from
_operator
address
Account attempting the transfer
_allowance
uint256
Current allowance
_value
uint256
BalanceTooLow
Balance too low to perform operation
NullTransfer
Invalid empty transfer
TokenTransferError
The token transfer failed during the minting or burning process
UnauthorizedTransfer
Invalid transfer recipients
Parameters
Name
Type
Description
_from
address
Account sending the funds in the invalid transfer
_to
address
Account receiving the funds in the invalid transfer
IOracleV1
Alluvial Finance Inc.
Oracle Interface (v1)
This interface exposes methods to handle the input from the allowed oracle members.Highly inspired by Lido's implementation.
Methods
function allowance(address _owner, address _spender) external view returns (uint256)
function approve(address _spender, uint256 _value) external nonpayable returns (bool)
function balanceOf(address _owner) external view returns (uint256)
function burn(address _recipient, uint256 _shares) external nonpayable
function decimals() external pure returns (uint8)
function decreaseAllowance(address _spender, uint256 _subtractableValue) external nonpayable returns (bool)
function increaseAllowance(address _spender, uint256 _additionalValue) external nonpayable returns (bool)
function initWLSETHV1(address _river) external nonpayable
function mint(address _recipient, uint256 _shares) external nonpayable
function name() external pure returns (string)
function sharesOf(address _owner) external view returns (uint256)
function symbol() external pure returns (string)
function totalSupply() external view returns (uint256)
function transfer(address _to, uint256 _value) external nonpayable returns (bool)
Adds new address as oracle member, giving the ability to push cl reports.
Only callable by the administrator. Modifying the quorum clears all the reporting data
Parameters
Name
Type
Description
_newOracleMember
address
Address of the new member
_newQuorum
uint256
New quorum value
getGlobalReportStatus
Retrieve member report status
Returns
Name
Type
Description
_0
uint256
The raw report status value
getLastReportedEpochId
Retrieve the last reported epoch id
The Oracle contracts expects reports on an epoch id >= that the returned value
Returns
Name
Type
Description
_0
uint256
The last reported epoch id
getMemberReportStatus
Retrieve member report status
Parameters
Name
Type
Description
_oracleMember
address
Address of member to check
Returns
Name
Type
Description
_0
bool
True if member has reported
getOracleMembers
Retrieve the list of oracle members
Returns
Name
Type
Description
_0
address[]
The oracle members
getQuorum
Retrieve the current quorum
Returns
Name
Type
Description
_0
uint256
The current quorum
getReportVariantDetails
Retrieve the details of a report variant
Parameters
Name
Type
Description
_idx
uint256
The index of the report variant
Returns
Name
Type
Description
_0
ReportsVariants.ReportVariantDetails
The report variant details
getReportVariantsCount
Retrieve report variants count
Returns
Name
Type
Description
_0
uint256
The count of report variants
getRiver
Retrieve River address
Returns
Name
Type
Description
_0
address
The address of River
initOracleV1
Initializes the oracle
Parameters
Name
Type
Description
_river
address
Address of the River contract, able to receive oracle input data after quorum is met
_administratorAddress
address
Address able to call administrative methods
_epochsPerFrame
uint64
CL spec parameter. Number of epochs in a frame.
_slotsPerEpoch
uint64
initOracleV1_1
Initializes the oracle
isMember
Returns true if address is member
Performs a naive search, do not call this on-chain, used as an off-chain helper
Parameters
Name
Type
Description
_memberAddress
address
Address of the member
Returns
Name
Type
Description
_0
bool
True if address is a member
removeMember
Removes an address from the oracle members.
Only callable by the administrator. Modifying the quorum clears all the reporting data. Remaining members that have already voted should vote again for the same frame.
Parameters
Name
Type
Description
_oracleMember
address
Address to remove
_newQuorum
uint256
New quorum value
reportConsensusLayerData
Parameters
Name
Type
Description
_report
IOracleManagerV1.ConsensusLayerReport
undefined
setMember
Changes the address of an oracle member
Only callable by the administrator or the member itselfCannot use an address already in use
Parameters
Name
Type
Description
_oracleMember
address
Address to change
_newAddress
address
New address for the member
setQuorum
Edits the quorum required to forward cl data to River
Modifying the quorum clears all the reporting data
Parameters
Name
Type
Description
_newQuorum
uint256
New quorum parameter
Events
AddMember
A member has been added to the oracle member list
Parameters
Name
Type
Description
member indexed
address
The address of the member
ClearedReporting
Cleared reporting data
RemoveMember
A member has been removed from the oracle member list
Parameters
Name
Type
Description
member indexed
address
The address of the member
ReportedConsensusLayerData
An oracle member performed a report
Parameters
Name
Type
Description
member indexed
address
The oracle member
variant indexed
bytes32
The variant of the report
report
IOracleManagerV1.ConsensusLayerReport
The raw report structure
voteCount
uint256
SetBounds
The report bounds have been changed
Parameters
Name
Type
Description
annualAprUpperBound
uint256
The maximum allowed apr. 10% means increases in balance extrapolated to a year should not exceed 10%.
relativeLowerBound
uint256
The maximum allowed balance decrease as a relative % of the total balance
SetLastReportedEpoch
The last reported epoch has changed
Parameters
Name
Type
Description
lastReportedEpoch
uint256
undefined
SetMember
A member address has been edited
Parameters
Name
Type
Description
oldAddress indexed
address
The previous member address
newAddress indexed
address
The new member address
SetQuorum
The storage quorum value has been changed
Parameters
Name
Type
Description
newQuorum
uint256
The new quorum value
SetRiver
The storage river address value has been changed
Parameters
Name
Type
Description
_river
address
The new river address
SetSpec
The consensus layer spec has been changed
Parameters
Name
Type
Description
epochsPerFrame
uint64
The number of epochs inside a frame (225 = 24 hours)
slotsPerEpoch
uint64
The number of slots inside an epoch (32 on ethereum mainnet)
secondsPerSlot
uint64
The time between two slots (12 seconds on ethereum mainnet)
genesisTime
uint64
Errors
AddressAlreadyInUse
The address is already in use by an oracle member
Parameters
Name
Type
Description
newAddress
address
The address already in use
AlreadyReported
The member already reported on the given epoch id
Parameters
Name
Type
Description
epochId
uint256
The epoch id provided as input
member
address
The oracle member
EpochTooOld
The provided epoch is too old compared to the expected epoch id
Parameters
Name
Type
Description
providedEpochId
uint256
The epoch id provided as input
minExpectedEpochId
uint256
The minimum epoch id expected
InvalidEpoch
Thrown when the reported epoch is invalid
Parameters
Name
Type
Description
epoch
uint256
The invalid epoch
ReportIndexOutOfBounds
Thrown when the report indexes fetched is out of bounds
Parameters
Name
Type
Description
index
uint256
Requested index
length
uint256
Size of the variant array
function addMember(address _newOracleMember, uint256 _newQuorum) external nonpayable
function getGlobalReportStatus() external view returns (uint256)
function getLastReportedEpochId() external view returns (uint256)
function getMemberReportStatus(address _oracleMember) external view returns (bool)
function getOracleMembers() external view returns (address[])
function getQuorum() external view returns (uint256)
function getReportVariantDetails(uint256 _idx) external view returns (struct ReportsVariants.ReportVariantDetails)
function getReportVariantsCount() external view returns (uint256)
function getRiver() external view returns (address)
CL spec parameter. Number of seconds between slots.
_genesisTime
uint64
CL spec parameter. Timestamp of the genesis slot.
_annualAprUpperBound
uint256
CL bound parameter. Maximum apr allowed for balance increase. Delta between updates is extrapolated on a year time frame.
_relativeLowerBound
uint256
CL bound parameter. Maximum relative balance decrease.
The vote count
quorum
uint256
undefined
The timestamp of block #0
Operate Validator Nodes
This guide is intended for Node Operators participating in the Liquid Collective protocol.
Operate Validator Nodes
Node Operators are validator infrastructure providers responsible for running validator nodes on the Ethereum consensus layer in the name of the protocol. Node Operators must have the capacity to scale to a large number of validator nodes, meet certain compliance requirements, and meet certain performance requirements, including Liquid Collective's Node Operator Performance SLAs.
Node Operators receive ETH delegation from the protocol and they are remunerated proportionally to the delegation they receive.
Operate Validator Nodes
Node Operator Procedure
Node Operators interested in receiving ETH delegation should go through the following flow.
One-time protocol onboarding
Node operator generates Node Operator wallet
Node Operator address gets approved on the Node Operator registry contracts
CLI
provides various commands to facilitate Node Operators in the process of managing validator keys.
CLI is compatible with the and can be used in conjunction with it.
Installation
The recommended installation is to use the public Docker image public.ecr.aws/alluvial/liquid-collective/lceth:v0.37.0
It is also possible to build the binary from sources.
Guidelines
Protocol Onboarding
Generate (or Import) Node Operator Wallet
The Node Operator needs a wallet to submit validator keys. The wallet must be approved on the Node Operator Registry Contract.
To generate such a wallet you can use the following command:
Once generated or imported you should securely store the key file and password for later usage, as you will need it each time you need to register keys.
It is also possible to import an existing wallet:
Approve Node Operator Wallet
A Node Operator should provide administrators with:
name: As the Node Operator will be publicly listed on the Node Operator contract
address: The Node Operator wallet address previously generated
Those values can be updated at any time after first approval.
Node Operator Index
Once approved, a Node Operator will get its operator index on the Node Operators Registry. This index will never change over time.
To get your node operator index, run the below command and find your name in the returned list.
Ongoing Operations: Pre-Registration of Validator Keys
Pre-registering validators consists of submitting new validators keys to the Node Operators registry contract so they can be picked for validation and funded.
As a Node Operator, you should typically pre-register new validators keys when:
It is the first time you pre-register keys
Most of the keys that you have pre-registered have been funded
It is the responsibility of the Node Operator to make sure validator keys are available for funding.
In the case that a Node Operator has no validator keys available, it will not receive an ETH delegation from the protocol.
Generate validator keys, deposit data and signatures
A Node Operator is responsible for generating validator keys in its own infrastructure.
For each generated key, a Node Operator is also expected to generate the corresponding DepositMessage and BLS12-381 signature as per the
Node Operators are required to set withdrawal credentials to the address of Withdrawal contract.
Per , once a Type 1 (0x01) withdrawal address is set those withdrawal credentials cannot be changed.
To get withdrawal credentials you can run:
As a result of the validator key generation, a Node Operator should obtain a JSON file matching the following format:
It is possible to use the to generate keys, which produces a file in the above format.
Node Operators are required to set the fee recipient of the validators to the ELFeeRecipient contract that is responsible to flow the execution layer network rewards to the core River contract.
To get the ELFeeRecipient address you can run:
Exec layer fee recipient address and withdrawal address are not the same.
Submit validator keys
Submit validator keys consists of sending a addValidatorKeys(...) transaction to the OperatorsRegistry contract. The transactions should be signed by the Node Operator address:
To submit validator keys you can run the following command:
The container runs with 65532:65532 and the keystore directory should be created and then chown'd to the user.
Once the transaction has been sent to the network and validated, the validator keys are listed on the Node Operators Registry contract and will be reviewed by the administrator.
Deposit and Node Activation
Node Operators should be careful that validator keys can be picked, funded, and deposited to the official Ethereum Deposit Contract at any time.
Once a validator key has been funded and deposited, it enters the activation queue. When this happens, the Node Operator should make sure that the corresponding validator key gets properly deployed to its validator infrastructure so the validator is ready when validator activation occurs.
We strongly recommend Node Operators effectively monitor the Deposit Contract, in particular watching DepositEvent to never miss an activation.
Watching the exit requests
Node Operators are responsible for exiting their own validators
Node Operators can use the provided Exit Daemon
Useful events:
FundedValidatorKeys
RequestedValidatorExits
Exit Daemon
Description
The Validator Exit Daemon is an off-chain application designed to help Liquid Collective Node Operators exit validator keys with ease.
Node Operators are responsible for exiting validator keys from the Consensus Layer, allowing withdrawn funds to be used for satisfying conversions of LsETH for ETH.
Flow
LsETH holders convert LsETH for ETH through the protocol, creating a request for ETH.
The protocol regularly rebalance's ETH positions. When it needs ETH funds to fulfill redeem demands, it withdraws funds from the Consensus Layer and signals Node Operators by emitting an event requesting validator keys to be exited. The protocol is responsible for selecting the Node Operators that need to exit keys, depending on the current validator key allocation.
Upon receiving a validator exit request event, the Node Operator exits the requested number of validator keys, which results in broadcasting ValidatorExit messages to the Consensus Layer. This step is facilitated by the Validator Exit Daemon application.
Technical considerations & assumptions:
Validator exit is triggered by broadcasting a ValidatorExit message signed with the validator's private key on the Consensus Layer.
We cannot rely on the Dual-Key exit design to also allow triggering the validator key exit from the withdrawal_credentials. Even if this option is preferred, it is not expected to be available on day 1 of the withdrawals.
Validator keys may be slashed, resulting in the keys undergoing the Consensus Layer slashing process and eventually leading to the withdrawal of funds after incurring penalties (this takes at least 36 days).
Architecture
The Validator Exit Daemon is a long-lived application containerized in a Docker image designed to be run by Node Operators in their infrastructure.
It accesses data from both the Execution Layer and Consensus Layer connected to nodes in the Node Operator infrastructure.
It assumes that Node Operators have an existing system and process in place for proceeding with validator key exits.
The Daemon can interact with the existing exit system through one or both of the following methods:
HTTP hook: Called by the Daemon each time a validator request exit event is emitted, and a validator key should be exited. Node Operators can configure the callback to match any endpoint.
API polling: The Daemon exposes an API that Node Operators can poll to retrieve the key to exit.
The Validator Exit Daemon will provide the following information to the Node Operator:
Number of validator keys to exit
Recommended keys to exit
Diagram
Sequence diagram
Dependencies
A synced Execution Layer client with a JSON-RPC endpoint enabled. All implementations are supported (Geth, Erigon, Besu, etc.)
A synced Consensus Layer client with an API endpoint enabled. All implementations are supported (Prysm, Teku, Lighthouse, etc.)
Installation
The recommended installation is to use the public Docker image public.ecr.aws/alluvial/liquid-collective/lceth:v0.37.0
For those running kubernetes and helm you can use this image:public.ecr.aws/alluvial/helm-charts/lceth:1.3.0
Usage
API
By default, the Exit daemon exposes an API route that Node Operators can use, either in conjunction with or without the HTTP hook.
This allows an operator to retrieve the recommended keys to exit at the current time.
Operator index could be retrieved with lceth operators list
The API meets the following requirements:
Webhook
The Exit daemon can run an HTTP hook system that sends validator exit request callbacks to the operator's existing systems when it receives a Validator Exit request event from the Consensus Layer.
The Exit daemon is stateless. If the webhook is enabled, it will send a call at each start if there is a pending exit request.
Operators can customize the webhook call by providing a template for the body, endpoint, and headers, and use the following macros to pass data related to the exit event:
total_requested_exits represents the total requested exits since the beginning of the contract. It’s a incremental-only counter emitted by the RequestedValidatorExits event.
validators_to_exit (as well as validators_to_exit_pubkeys & validators_to_exit_indexes) is an array of the validators to exit at a given time. To get them, the exit daemon fetches all the keys of an operator (via the
The webhook templating imports the . Which means additional functions are available to format the output.
For instance:
using environment variables via {{env "ENV_VAR_NAME"}}
Example of webhook template:
Usage output:
On-going operations
Pre-registration of validator keys
Node Operator generates validator keys in its infrastructure with expected configuration (withdrawal credentials, execution layer fee recipient, etc.)
Node Operator submits validator keys to the Node Operators registry contract by sending a transaction using the Node Operator wallet
From this point in time, validator keys should be ready to get funded
Protocol administrator reviews and confirms added keys are valid
Validates validator keys, ensuring withdrawal credentials, deposit data, and signatures are correct
Administrator increases operator limit making validator keys eligible for funding. From this point in time, validators keys can be funded at any time
Validator keys are funded and activated
Protocol regularly picks eligible validator keys and deposits them to the official Ethereum deposit contract
Once deposited, validator keys enter the activation queue as per the standard Ethereum staking procedure
Run the Exit Daemon
Node Operators are responsible for exiting their own validators
Node Operators have the possibility of running the lceth exit daemon in order to be notified when they should exit their validators
After validator keys pass through the exit queue, funds are withdrawn to the LC Withdraw contract, and the Liquid Collective protocol takes over the ETH to satisfy the LsETH conversion requests.
Existing Liquid Collective validator keys have all been set with a 0x1 prefix and point to the Withdraw contract.
Liquid Collective Node Operators use diverse infrastructure base layers (clouds, bare metal, containers/orchestration), client software (Prysm, Lighthouse, etc.), and may use or not use signers (e.g., Web3Signer). This diversity is expected to grow with staking innovations (e.g., DVT).
Liquid Collective Node Operators have (or are building) infrastructure & processes
FundedValidatorKeys
event), check their status on the consensus layer to know those already exited, and then make a diff with
total_requested_exits
to know how many keys are remaining to exit.
printing array via {{validators_to_exit_pubkeys | toJson}}
creating a quoted string from an array via {{.validators_to_exit_indexes | join "," | quote}}
computing array length via {{.validators_to_exit_indexes | len}}
/// @notice Adds new keys for an operator
/// @dev Only callable by the administrator or the operator address
/// @param _name The name identifying the operator
/// @param _keyCount The amount of keys provided
/// @param _publicKeys Public keys of the validator, concatenated
/// @param _signatures Signatures of the validator keys, concatenated
function addValidatorKeys(
string calldata _name,
uint256 _keyCount,
bytes calldata _publicKeys,
bytes calldata _signatures
)
| Name | Type | Description |
| -------------------------- | -------- | ----------------------------------------- |
| chain_id | string | Network identifier |
| total_requested_exits | int | Number of validators requested to exit |
| validators_to_exit_indexes | int[] | List of validators pubkey to exit |
| validators_to_exit_pubkeys | string[] | List of validators index to exit |
| validators_to_exit | object[] | List of validators pubkey + index to exit |
Run exit daemon
Usage:
lceth exit run [flags]
Flags:
--eth-cl-addr string Address of the Ethereum consensus layer node to connect to [env: ETH_CL_ADDR]
--operator-idx int Index of the operator running the daemon [env: OPERATOR_INDEX]
--webhook enable 'webhook' [env: WEBHOOK]
--webhook-endpoint string Go template describing the endpoint that the webhook will call [env: WEBHOOK_ENDPOINT]
--webhook-method string HTTP method to query the webhook's endpoint [env: WEBHOOK_METHOD]
--webhook-template-header stringToString Go template describing the body to be sent to the webhook's endpoint [env: WEBHOOK_TEMPLATE_HEADER] (default [])
--webhook-template-body string Go templates describing the headers to be sent to the webhook [env: WEBHOOK_TEMPLATE_BODY]
--webhook-retry int Retry limit in case of webhook-endpoint returns error with status code 5xx [env: WEBHOOK_RETRY]
--webhook-timeout duration Delay to wait before abort request sent to webhook-endpoint [env: WEBHOOK_TIMEOUT]
--rpc-call-retry int How many time should we retry failed rpc calls [env: RPC_CALL_RETRY] (default 3)
--block-log-fetch-step int How many blocks are fetched at once when fetching logs [env: BLOCK_LOG_FETCH_STEP] (default 100000)
--max-workers int How many goroutines to use on threaded tasks [env: MAX_WORKERS] (default 10)
--batch-fetch-validators Whether to batch when querying the consensus layer to get validators' data (recommended if timeout issues arise) [env: BATCH_FETCH_VALIDATORS]
--max-get-validators int Max size of the batch when querying the consensus layer to get validators' data, only useful if using --batch-fetch-validators [env: MAX_GET_VALIDATORS] (default 1000)
--loop-sleep-time duration How often should the exit-daemon run [env: LOOP_SLEEP_TIME] (default 5m0s)
-h, --help help for run
Global Flags:
--allowlist-addr string Address of the Allowlist contract [env: ALLOWLIST_ADDR]
--deployment-block uint Deployment block of the contracts [env: DEPLOYMENT_BLOCK]
--el-fee-recipient-addr string Address of the Execution Layer fee recipient contract [env: EL_FEE_RECIPIENT_ADDR]
--eth-el-addr string JSON-RPC address of the Ethereum execution layer node to connect to [env: ETH_EL_ADDR]
--keystore-password string Password used to encrypt key files [env: KEYSTORE_PASSWORD]
--keystore-path string Directory where to store keys [env: KEYSTORE_PATH]
--log-format string Log output format (text or json) [env: LOG_FORMAT] (default "text")
--log-level string Log output level [env: LOG_LEVEL] (default "info")
--operators-registry-addr string Address of the Operators Registry contract [env: OPERATORS_REGISTRY_ADDR]
--oracle-addr string Address of the Oracle contract [env: ORACLE_ADDR]
--redeem-manager-addr string Address of the RedeemManager contract [env: REDEEM_MANAGER_ADDR]
--river-addr string Address of the River contract [env: RIVER_ADDR]
--tlc-addr string Address of the TLC contract [env: TLC_ADDR]
--withdraw-addr string Address of the Withdraw contract [env: WITHDRAW_ADDR]
--wls-eth-addr string Address of the WlsEth contract [env: WLSETH_ADDR]
RedeemManagerV1
Alluvial Finance Inc.
Redeem Manager (v1)
This contract handles the redeem requests of all users
Methods
claimRedeemRequests
Claims the rewards of the provided redeem request ids
Parameters
Name
Type
Description
Returns
Name
Type
Description
claimRedeemRequests
Claims the rewards of the provided redeem request ids
Parameters
Name
Type
Description
Returns
Name
Type
Description
getBufferedExceedingEth
Retrieve the amount of redeemed LsETH pending to be supplied with withdrawn ETH
Returns
Name
Type
Description
getRedeemDemand
Retrieve the amount of LsETH waiting to be exited
Returns
Name
Type
Description
getRedeemRequestCount
Retrieve the global count of redeem requests
Returns
Name
Type
Description
getRedeemRequestDetails
Retrieve the details of a specific redeem request
Parameters
Name
Type
Description
Returns
Name
Type
Description
getRiver
Retrieve River address
Returns
Name
Type
Description
getWithdrawalEventCount
Retrieve the global count of withdrawal events
Returns
Name
Type
Description
getWithdrawalEventDetails
Retrieve the details of a specific withdrawal event
Parameters
Name
Type
Description
Returns
Name
Type
Description
initializeRedeemManagerV1
Parameters
Name
Type
Description
initializeRedeemManagerV1_2
pullExceedingEth
Pulls exceeding buffer eth
Parameters
Name
Type
Description
reportWithdraw
Reports a withdraw event from River
Parameters
Name
Type
Description
requestRedeem
Creates a redeem request
Parameters
Name
Type
Description
Returns
Name
Type
Description
requestRedeem
Creates a redeem request using msg.sender as recipient
Parameters
Name
Type
Description
Returns
Name
Type
Description
resolveRedeemRequests
Resolves the provided list of redeem request ids
The result is an array of equal length with ids or error code-1 means that the request is not satisfied yet-2 means that the request is out of bounds-3 means that the request has already been claimedThis call was created to be called by an off-chain interface, the output could then be used to perform the claimRewards call in a regular transaction
Parameters
Name
Type
Description
Returns
Name
Type
Description
version
Retrieves the version of the contract
Returns
Name
Type
Description
Events
ClaimedRedeemRequest
Emitted when a redeem request claim has been processed and matched at least once and funds are sent to the recipient
Parameters
Name
Type
Description
Initialize
Emitted when the contract is properly initialized
Parameters
Name
Type
Description
ReportedWithdrawal
Emitted when a withdrawal event is created
Parameters
Name
Type
Description
RequestedRedeem
Emitted when a redeem request is created
Parameters
Name
Type
Description
SatisfiedRedeemRequest
Emitted when a redeem request has been satisfied and filled (even partially) from a withdrawal event
Parameters
Name
Type
Description
SetRedeemDemand
Emitted when the redeem demand is set
Parameters
Name
Type
Description
SetRiver
Emitted when the River address is set
Parameters
Name
Type
Description
Errors
ClaimInitiatorIsDenied
Thrown when the claim initiator is denied
ClaimRecipientIsDenied
Thrown when the claim recipient is denied
ClaimRedeemFailed
Thrown when the payment after a claim failed
Parameters
Name
Type
Description
DoesNotMatch
Thrown when the redeem request and withdrawal event are not matching during claim
Parameters
Name
Type
Description
IncompatibleArrayLengths
Thrown when the provided arrays don't have matching lengths
InvalidInitialization
An error occurred during the initialization
Parameters
Name
Type
Description
InvalidZeroAddress
The address is zero
InvalidZeroAmount
Thrown When a zero value is provided
RecipientIsDenied
Thrown when the recipient of redeemRequest is denied
RedeemRequestAlreadyClaimed
Thrown when the redeem request id is already claimed
Parameters
Name
Type
Description
RedeemRequestOutOfBounds
Thrown when the provided redeem request id is out of bounds
Parameters
Name
Type
Description
TransferError
Thrown when a transfer error occurred with LsETH
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
WithdrawalEventOutOfBounds
Thrown when the withdrawal request id if out of bounds
Parameters
Name
Type
Description
WithdrawalExceedsRedeemDemand
Thrown when the provided withdrawal event exceeds the redeem demand
Parameters
Name
Type
Description
OracleV1
Alluvial Finance Inc.
Oracle (v1)
This contract handles the input from the allowed oracle members. Highly inspired by Lido's implementation.
Methods
remainingLsEthAmount
uint256
The amount of LsETH remaining
id
uint32
The id of the new redeem request
lsEthAmountRemaining
uint256
The amount of LsETH remaining
ethAmountExceeding
uint256
The amount of eth added to the exceeding buffer
redeemRequestIds
uint32[]
undefined
withdrawalEventIds
uint32[]
undefined
skipAlreadyClaimed
bool
undefined
_depth
uint16
claimStatuses
uint8[]
The list of claim statuses. 0 for fully claimed, 1 for partially claimed, 2 for skipped
_redeemRequestIds
uint32[]
The list of redeem requests to claim
_withdrawalEventIds
uint32[]
The list of withdrawal events to use for every redeem request claim
claimStatuses
uint8[]
The list of claim statuses. 0 for fully claimed, 1 for partially claimed, 2 for skipped
_0
uint256
The amount of eth in the buffer
_0
uint256
The amount of LsETH waiting to be exited
_0
uint256
undefined
_redeemRequestId
uint32
The id of the request
_0
RedeemQueueV2.RedeemRequest
The redeem request details
_0
address
The address of River
_0
uint256
undefined
_withdrawalEventId
uint32
The id of the withdrawal event
_0
WithdrawalStack.WithdrawalEvent
The withdrawal event details
_river
address
The address of the River contract
_max
uint256
The maximum amount that should be pulled
_lsETHWithdrawable
uint256
The amount of LsETH that can be redeemed due to this new withdraw event
_lsETHAmount
uint256
The amount of LsETH to redeem
_recipient
address
The recipient owning the redeem request
redeemRequestId
uint32
The id of the redeem request
_lsETHAmount
uint256
The amount of LsETH to redeem
redeemRequestId
uint32
The id of the redeem request
_redeemRequestIds
uint32[]
The list of redeem requests to resolve
withdrawalEventIds
int64[]
The list of withdrawal events matching every redeem request (or error codes)
_0
string
Version of the contract
redeemRequestId indexed
uint32
The id of the redeem request
recipient indexed
address
The address receiving the redeem request funds
ethAmount
uint256
The amount of eth retrieved
lsEthAmount
uint256
version
uint256
New version of the contracts
cdata
bytes
Complete calldata that was used during the initialization
height
uint256
The height of the withdrawal event in LsETH
amount
uint256
The amount of the withdrawal event in LsETH
ethAmount
uint256
The amount of eth to distribute to claimers
id
uint32
recipient indexed
address
The recipient of the redeem request
height
uint256
The height of the redeem request in LsETH
amount
uint256
The amount of the redeem request in LsETH
maxRedeemableEth
uint256
redeemRequestId indexed
uint32
The id of the redeem request
withdrawalEventId indexed
uint32
The id of the withdrawal event used to fill the request
lsEthAmountSatisfied
uint256
The amount of LsETH filled
ethAmountSatisfied
uint256
oldRedeemDemand
uint256
The old redeem demand
newRedeemDemand
uint256
The new redeem demand
river
address
The new river address
recipient
address
The recipient of the payment
rdata
bytes
The revert data
redeemRequestId
uint256
The provided redeem request id
withdrawalEventId
uint256
The provided associated withdrawal event id
version
uint256
The version that was attempting to be initialized
expectedVersion
uint256
The version that was expected
id
uint256
The redeem request id
id
uint256
The redeem request id
caller
address
Address performing the call
id
uint256
The withdrawal event id
withdrawalAmount
uint256
The amount of the withdrawal event
redeemDemand
uint256
The current redeem demand
The maximum recursive depth for the resolution of the redeem requests
The total amount of LsETH used to redeem the eth
The id of the withdrawal event
The maximum amount of eth that can be redeemed from this request
Only callable by the pending admin. Resets the pending admin if successful.
addMember
Adds new address as oracle member, giving the ability to push cl reports.
Only callable by the administrator. Modifying the quorum clears all the reporting data
Parameters
Name
Type
Description
_newOracleMember
address
Address of the new member
_newQuorum
uint256
New quorum value
getAdmin
Retrieves the current admin address
Returns
Name
Type
Description
_0
address
The admin address
getGlobalReportStatus
Retrieve member report status
Returns
Name
Type
Description
_0
uint256
The raw report status value
getLastReportedEpochId
Retrieve the last reported epoch id
The Oracle contracts expects reports on an epoch id >= that the returned value
Returns
Name
Type
Description
_0
uint256
The last reported epoch id
getMemberReportStatus
Retrieve member report status
Parameters
Name
Type
Description
_oracleMember
address
Address of member to check
Returns
Name
Type
Description
_0
bool
True if member has reported
getOracleMembers
Retrieve the list of oracle members
Returns
Name
Type
Description
_0
address[]
The oracle members
getPendingAdmin
Retrieve the current pending admin address
Returns
Name
Type
Description
_0
address
The pending admin address
getQuorum
Retrieve the current quorum
Returns
Name
Type
Description
_0
uint256
The current quorum
getReportVariantDetails
Retrieve the details of a report variant
Parameters
Name
Type
Description
_idx
uint256
The index of the report variant
Returns
Name
Type
Description
_0
ReportsVariants.ReportVariantDetails
The report variant details
getReportVariantsCount
Retrieve report variants count
Returns
Name
Type
Description
_0
uint256
The count of report variants
getRiver
Retrieve River address
Returns
Name
Type
Description
_0
address
The address of River
initOracleV1
Initializes the oracle
Parameters
Name
Type
Description
_riverAddress
address
undefined
_administratorAddress
address
Address able to call administrative methods
_epochsPerFrame
uint64
CL spec parameter. Number of epochs in a frame.
_slotsPerEpoch
uint64
initOracleV1_1
Initializes the oracle
isMember
Returns true if address is member
Performs a naive search, do not call this on-chain, used as an off-chain helper
Parameters
Name
Type
Description
_memberAddress
address
Address of the member
Returns
Name
Type
Description
_0
bool
True if address is a member
proposeAdmin
Proposes a new address as admin
This security prevents setting an invalid address as an admin. The pending admin has to claim its ownership of the contract, and prove that the new address is able to perform regular transactions.
Parameters
Name
Type
Description
_newAdmin
address
New admin address
removeMember
Removes an address from the oracle members.
Only callable by the administrator. Modifying the quorum clears all the reporting dataRemaining members that have already voted should vote again for the same frame.
Parameters
Name
Type
Description
_oracleMember
address
Address to remove
_newQuorum
uint256
New quorum value
reportConsensusLayerData
Parameters
Name
Type
Description
_report
IOracleManagerV1.ConsensusLayerReport
undefined
setMember
Changes the address of an oracle member
Only callable by the administrator or the member itselfCannot use an address already in use
Parameters
Name
Type
Description
_oracleMember
address
Address to change
_newAddress
address
New address for the member
setQuorum
Edits the quorum required to forward cl data to River
Modifying the quorum clears all the reporting data
Parameters
Name
Type
Description
_newQuorum
uint256
New quorum parameter
version
Retrieves the version of the contract
Returns
Name
Type
Description
_0
string
Version of the contract
Events
AddMember
A member has been added to the oracle member list
Parameters
Name
Type
Description
member indexed
address
The address of the member
ClearedReporting
Cleared reporting data
Initialize
Emitted when the contract is properly initialized
Parameters
Name
Type
Description
version
uint256
New version of the contracts
cdata
bytes
Complete calldata that was used during the initialization
RemoveMember
A member has been removed from the oracle member list
Parameters
Name
Type
Description
member indexed
address
The address of the member
ReportedConsensusLayerData
An oracle member performed a report
Parameters
Name
Type
Description
member indexed
address
The oracle member
variant indexed
bytes32
The variant of the report
report
IOracleManagerV1.ConsensusLayerReport
The raw report structure
voteCount
uint256
SetAdmin
The admin address changed
Parameters
Name
Type
Description
admin indexed
address
New admin address
SetBounds
The report bounds have been changed
Parameters
Name
Type
Description
annualAprUpperBound
uint256
The maximum allowed apr. 10% means increases in balance extrapolated to a year should not exceed 10%.
relativeLowerBound
uint256
The maximum allowed balance decrease as a relative % of the total balance
SetLastReportedEpoch
The last reported epoch has changed
Parameters
Name
Type
Description
lastReportedEpoch
uint256
undefined
SetMember
A member address has been edited
Parameters
Name
Type
Description
oldAddress indexed
address
The previous member address
newAddress indexed
address
The new member address
SetPendingAdmin
The pending admin address changed
Parameters
Name
Type
Description
pendingAdmin indexed
address
New pending admin address
SetQuorum
The storage quorum value has been changed
Parameters
Name
Type
Description
newQuorum
uint256
The new quorum value
SetRiver
The storage river address value has been changed
Parameters
Name
Type
Description
_river
address
The new river address
SetSpec
The consensus layer spec has been changed
Parameters
Name
Type
Description
epochsPerFrame
uint64
The number of epochs inside a frame (225 = 24 hours)
slotsPerEpoch
uint64
The number of slots inside an epoch (32 on ethereum mainnet)
secondsPerSlot
uint64
The time between two slots (12 seconds on ethereum mainnet)
genesisTime
uint64
Errors
AddressAlreadyInUse
The address is already in use by an oracle member
Parameters
Name
Type
Description
newAddress
address
The address already in use
AlreadyReported
The member already reported on the given epoch id
Parameters
Name
Type
Description
epochId
uint256
The epoch id provided as input
member
address
The oracle member
EpochTooOld
The provided epoch is too old compared to the expected epoch id
Parameters
Name
Type
Description
providedEpochId
uint256
The epoch id provided as input
minExpectedEpochId
uint256
The minimum epoch id expected
InvalidArgument
The argument was invalid
InvalidCall
The call was invalid
InvalidEpoch
Thrown when the reported epoch is invalid
Parameters
Name
Type
Description
epoch
uint256
The invalid epoch
InvalidInitialization
An error occurred during the initialization
Parameters
Name
Type
Description
version
uint256
The version that was attempting to be initialized
expectedVersion
uint256
The version that was expected
InvalidZeroAddress
The address is zero
ReportIndexOutOfBounds
Thrown when the report indexes fetched is out of bounds
Parameters
Name
Type
Description
index
uint256
Requested index
length
uint256
Size of the variant array
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
caller
address
Address performing the call
function acceptAdmin() external nonpayable
function addMember(address _newOracleMember, uint256 _newQuorum) external nonpayable
function getAdmin() external view returns (address)
function getGlobalReportStatus() external view returns (uint256)
function getLastReportedEpochId() external view returns (uint256)
function getMemberReportStatus(address _oracleMember) external view returns (bool)
function getOracleMembers() external view returns (address[])
function getPendingAdmin() external view returns (address)
function getQuorum() external view returns (uint256)
function getReportVariantDetails(uint256 _idx) external view returns (struct ReportsVariants.ReportVariantDetails)
function getReportVariantsCount() external view returns (uint256)
function getRiver() external view returns (address)
CL spec parameter. Number of seconds between slots.
_genesisTime
uint64
CL spec parameter. Timestamp of the genesis slot.
_annualAprUpperBound
uint256
CL bound parameter. Maximum apr allowed for balance increase. Delta between updates is extrapolated on a year time frame.
_relativeLowerBound
uint256
CL bound parameter. Maximum relative balance decrease.
The vote count
quorum
uint256
undefined
The timestamp of block #0
ITLCV1
Alluvial Finance Inc.
TLC Interface (v1)
TLC token interface
Methods
allowance
Returns the remaining number of tokens that spender will be allowed to spend on behalf of owner through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.
Parameters
Name
Type
Description
Returns
Name
Type
Description
approve
Sets amount as the allowance of spender over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.
Parameters
Name
Type
Description
Returns
Name
Type
Description
balanceOf
Returns the amount of tokens owned by account.
Parameters
Name
Type
Description
Returns
Name
Type
Description
computeVestingReleasableAmount
Computes the releasable amount of tokens for a vesting schedule.
Parameters
Name
Type
Description
Returns
Name
Type
Description
computeVestingVestedAmount
Computes the vested amount of tokens for a vesting schedule.
Parameters
Name
Type
Description
Returns
Name
Type
Description
createVestingSchedule
Creates a new vesting scheduleThere may delay between the time a user should start vesting tokens and the time the vesting schedule is actually created on the contract.Typically a user joins the Liquid Collective but some weeks pass before the user gets all legal agreements in place and signed for the token grant emission to happen. In this case, the vesting schedule created for the token grant would start on the join date which is in the past.
As vesting schedules can be created in the past, this means that you should be careful when creating a vesting schedule and what duration parameters you use as this contract would allow creating a vesting schedule in the past and even a vesting schedule that has already ended.
Parameters
Name
Type
Description
Returns
Name
Type
Description
delegate
Delegates votes from the sender to delegatee.
Parameters
Name
Type
Description
delegateBySig
Delegates votes from signer to delegatee.
Parameters
Name
Type
Description
delegateVestingEscrow
Delegate vesting escrowed tokens
Parameters
Name
Type
Description
Returns
Name
Type
Description
delegates
Returns the delegate that account has chosen.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getPastTotalSupply
Returns the total supply of votes available at a specific moment in the past. If the clock() is configured to use block numbers, this will return the value at the end of the corresponding block. NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. Votes that have not been delegated are still part of total supply, even though they would not participate in a vote.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getPastVotes
Returns the amount of votes that account had at a specific moment in the past. If the clock() is configured to use block numbers, this will return the value at the end of the corresponding block.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getVestingSchedule
Get vesting schedule
The vesting schedule structure represents a static configuration used to compute the desired vesting details of a beneficiary at all times. The values won't change even after tokens are released. The only dynamic field of the structure is end, and is updated whenever a vesting schedule is revoked
Parameters
Name
Type
Description
Returns
Name
Type
Description
getVestingScheduleCount
Get count of vesting schedules
Returns
Name
Type
Description
getVotes
Returns the current amount of votes that account has.
Parameters
Name
Type
Description
Returns
Name
Type
Description
initTLCV1
Initializes the TLC Token
Parameters
Name
Type
Description
isGlobalUnlockedScheduleIgnored
Get vesting global unlock schedule activation status for a vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
migrateVestingSchedules
Migrates the vesting schedule state structures
releaseVestingSchedule
Release vesting scheduleWhen tokens are released from the escrow, the delegated address of the escrow will see its voting power decrease.The beneficiary has to make sure its delegation parameters are set properly to be able to use/delegate the voting power of its balance.
Parameters
Name
Type
Description
Returns
Name
Type
Description
revokeVestingSchedule
Revoke vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
totalSupply
Returns the amount of tokens in existence.
Returns
Name
Type
Description
transfer
Moves amount tokens from the caller's account to to. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.
Parameters
Name
Type
Description
Returns
Name
Type
Description
transferFrom
Moves amount tokens from from to to using the allowance mechanism. amount is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.
Parameters
Name
Type
Description
Returns
Name
Type
Description
vestingEscrow
Get the address of the escrow for a vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
Approval
Emitted when the allowance of a spender for an owner is set by a call to {approve}. value is the new allowance.
Parameters
Name
Type
Description
CreatedVestingSchedule
A new vesting schedule has been created
Parameters
Name
Type
Description
DelegateChanged
Emitted when an account changes their delegate.
Parameters
Name
Type
Description
DelegateVotesChanged
Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
Parameters
Name
Type
Description
DelegatedVestingEscrow
Vesting escrow has been delegated
Parameters
Name
Type
Description
ReleasedVestingSchedule
Vesting schedule has been released
Parameters
Name
Type
Description
RevokedVestingSchedule
Vesting schedule has been revoked
Parameters
Name
Type
Description
Transfer
Emitted when value tokens are moved from one account (from) to another (to). Note that value may be zero.
Parameters
Name
Type
Description
Errors
GlobalUnlockUnderlfow
Underflow in global unlock logic (should never happen)
InvalidRevokedVestingScheduleEnd
Attempt to revoke a vesting schedule with an invalid end parameter
InvalidVestingScheduleParameter
Invalid parameter for a vesting schedule
Parameters
Name
Type
Description
UnsufficientVestingScheduleCreatorBalance
Vesting schedule creator has unsufficient balance to create vesting schedule
VestingScheduleIsLocked
The vesting schedule is locked
VestingScheduleNotRevocable
The vesting schedule is not revocable
VestingScheduleNotRevocableInPast
Attempt to revoke a schedule in the past
ZeroReleasableAmount
No token to release
IOperatorsRegistryV1
Alluvial Finance Inc.
Operators Registry Interface (v1)
This interface exposes methods to handle the list of operators and their keys
Methods
_lockDuration
uint32
duration during which tokens are locked (in seconds)
_revocable
bool
whether the vesting schedule is revocable or not
_amount
uint256
amount of token attributed by the vesting schedule
_beneficiary
address
address of the beneficiary of the tokens
_delegatee
address
address to delegate escrow voting power to
_ignoreGlobalUnlockSchedule
bool
whether the vesting schedule should ignore the global lock
r
bytes32
undefined
s
bytes32
undefined
owner
address
undefined
spender
address
undefined
_0
uint256
undefined
spender
address
undefined
amount
uint256
undefined
_0
bool
undefined
account
address
undefined
_0
uint256
undefined
_index
uint256
index of the vesting schedule
_0
uint256
amount of releasable tokens
_index
uint256
index of the vesting schedule
_0
uint256
amount of vested tokens
_start
uint64
start time of the vesting
_cliffDuration
uint32
duration to vesting cliff (in seconds)
_duration
uint32
total vesting schedule duration after which all tokens are vested (in seconds)
_periodDuration
uint32
_0
uint256
index of the created vesting schedule
delegatee
address
undefined
delegatee
address
undefined
nonce
uint256
undefined
expiry
uint256
undefined
v
uint8
_index
uint256
index of the vesting schedule
_delegatee
address
address to delegate the token to
_0
bool
True on success
account
address
undefined
_0
address
undefined
timepoint
uint256
undefined
_0
uint256
undefined
account
address
undefined
timepoint
uint256
undefined
_0
uint256
undefined
_index
uint256
Index of the vesting schedule
_0
VestingSchedulesV2.VestingSchedule
undefined
_0
uint256
count of vesting schedules
account
address
undefined
_0
uint256
undefined
_account
address
The initial account to grant all the minted tokens
_index
uint256
Index of the vesting schedule
_0
bool
true if the vesting schedule should ignore the global unlock schedule
_index
uint256
Index of the vesting schedule to release
_0
uint256
released amount
_index
uint256
Index of the vesting schedule to revoke
_end
uint64
End date for the schedule
returnedAmount
uint256
amount returned to the vesting schedule creator
_0
uint256
undefined
to
address
undefined
amount
uint256
undefined
_0
bool
undefined
from
address
undefined
to
address
undefined
amount
uint256
undefined
_0
bool
undefined
_index
uint256
Index of the vesting schedule
_0
address
address of the escrow
owner indexed
address
undefined
spender indexed
address
undefined
value
uint256
undefined
index
uint256
Vesting schedule index
creator indexed
address
Creator of the vesting schedule
beneficiary indexed
address
Vesting beneficiary address
amount
uint256
delegator indexed
address
undefined
fromDelegate indexed
address
undefined
toDelegate indexed
address
undefined
delegate indexed
address
undefined
previousBalance
uint256
undefined
newBalance
uint256
undefined
index
uint256
Vesting schedule index
oldDelegatee indexed
address
old delegatee
newDelegatee indexed
address
new delegatee
beneficiary indexed
address
index
uint256
Vesting schedule index
releasedAmount
uint256
Amount of tokens released to the beneficiary
index
uint256
Vesting schedule index
returnedAmount
uint256
Amount of tokens returned to the creator
newEnd
uint256
New end timestamp after revoke action
from indexed
address
undefined
to indexed
address
undefined
value
uint256
undefined
msg
string
undefined
duration of a period after which new tokens unlock (in seconds)
undefined
Vesting schedule amount
vesting schedule beneficiary
function allowance(address owner, address spender) external view returns (uint256)
function approve(address spender, uint256 amount) external nonpayable returns (bool)
function balanceOf(address account) external view returns (uint256)
function computeVestingReleasableAmount(uint256 _index) external view returns (uint256)
function computeVestingVestedAmount(uint256 _index) external view returns (uint256)
event Transfer(address indexed from, address indexed to, uint256 value)
error GlobalUnlockUnderlfow()
error InvalidRevokedVestingScheduleEnd()
error InvalidVestingScheduleParameter(string msg)
error UnsufficientVestingScheduleCreatorBalance()
error VestingScheduleIsLocked()
error VestingScheduleNotRevocable()
error VestingScheduleNotRevocableInPast()
error ZeroReleasableAmount()
addOperator
Adds an operator to the registry
Only callable by the administrator
Parameters
Name
Type
Description
_name
string
The name identifying the operator
_operator
address
The address representing the operator, receiving the rewards
Returns
Name
Type
Description
_0
uint256
The index of the new operator
addValidators
Adds new keys for an operator
Only callable by the administrator or the operator address
Parameters
Name
Type
Description
_index
uint256
The operator index
_keyCount
uint32
The amount of keys provided
_publicKeysAndSignatures
bytes
Public keys of the validator, concatenated
demandValidatorExits
Increases the exit request demand
This method is only callable by the river contract, and to actually forward the information to the node operators via event emission, the unprotected requestValidatorExits method must be called
Parameters
Name
Type
Description
_count
uint256
The amount of exit requests to add to the demand
_depositedValidatorCount
uint256
The total deposited validator count
getCurrentValidatorExitsDemand
Get the current exit request demand waiting to be triggeredThis value is the amount of exit requests that are demanded and not yet performed by the contract
Returns
Name
Type
Description
_0
uint256
The current exit request demand
getNextValidatorsToDepositFromActiveOperators
Get the next validators that would be funded
Parameters
Name
Type
Description
_count
uint256
Count of validators that would be funded next
Returns
Name
Type
Description
publicKeys
bytes[]
An array of fundable public keys
signatures
bytes[]
An array of signatures linked to the public keys
getOperator
Get operator details
Parameters
Name
Type
Description
_index
uint256
The index of the operator
Returns
Name
Type
Description
_0
OperatorsV2.Operator
The details of the operator
getOperatorCount
Get operator count
Returns
Name
Type
Description
_0
uint256
The operator count
getOperatorStoppedValidatorCount
Retrieve the stopped validator count for an operator index
Parameters
Name
Type
Description
_idx
uint256
The index of the operator
Returns
Name
Type
Description
_0
uint32
The stopped validator count of the operator
getRiver
Retrieve the River address
Returns
Name
Type
Description
_0
address
The address of River
getStoppedAndRequestedExitCounts
Retrieve the total stopped and requested exit count
Returns
Name
Type
Description
_0
uint32
The total stopped count
_1
uint256
The total requested exit count
getStoppedValidatorCountPerOperator
Retrieve the raw stopped validators array from storage
Returns
Name
Type
Description
_0
uint32[]
The stopped validator array
getTotalStoppedValidatorCount
Retrieve the total stopped validator count
Returns
Name
Type
Description
_0
uint32
The total stopped validator count
getTotalValidatorExitsRequested
Retrieve the total requested exit countThis value is the amount of exit requests that have been performed, emitting an event for operators to catch
Returns
Name
Type
Description
_0
uint256
The total requested exit count
getValidator
Get the details of a validator
Parameters
Name
Type
Description
_operatorIndex
uint256
The index of the operator
_validatorIndex
uint256
The index of the validator
Returns
Name
Type
Description
publicKey
bytes
The public key of the validator
signature
bytes
The signature used during deposit
funded
bool
True if validator has been funded
initOperatorsRegistryV1
Initializes the operators registry
Parameters
Name
Type
Description
_admin
address
Admin in charge of managing operators
_river
address
Address of River system
initOperatorsRegistryV1_1
Initializes the operators registry for V1_1
listActiveOperators
Retrieve the active operator set
Returns
Name
Type
Description
_0
OperatorsV2.Operator[]
The list of active operators and their details
pickNextValidatorsToDeposit
Retrieve validator keys based on operator statuses
Parameters
Name
Type
Description
_count
uint256
Max amount of keys requested
Returns
Name
Type
Description
publicKeys
bytes[]
An array of public keys
signatures
bytes[]
An array of signatures linked to the public keys
removeValidators
Remove validator keys
Only callable by the administrator or the operator address. The indexes must be provided sorted in decreasing order and duplicate-free, otherwise the method will revertThe operator limit will be set to the lowest deleted key index if the operator's limit wasn't equal to its total key count. The operator or the admin cannot remove funded keysWhen removing validators, the indexes of specific unfunded keys can be changed in order to properly remove the keys from the storage array. Beware of this specific behavior when chaining calls as the targeted public key indexes can point to a different key after a first call was made and performed some swaps
Parameters
Name
Type
Description
_index
uint256
The operator index
_indexes
uint256[]
The indexes of the keys to remove
reportStoppedValidatorCounts
Allows river to override the stopped validators arrayThis actions happens during the Oracle report processing
Parameters
Name
Type
Description
_stoppedValidatorCounts
uint32[]
The new stopped validators array
_depositedValidatorCount
uint256
The total deposited validator count
requestValidatorExits
Public endpoint to consume the exit request demand and perform the actual exit requestsThe selection algorithm will pick validators based on their active validator countsThis value is computed by using the count of funded keys and taking into account the stopped validator counts and exit requests
Parameters
Name
Type
Description
_count
uint256
Max amount of exits to request
setOperatorAddress
Changes the operator address of an operator
Only callable by the administrator or the previous operator address
Parameters
Name
Type
Description
_index
uint256
The operator index
_newOperatorAddress
address
The new address of the operator
setOperatorLimits
Changes the operator staking limit
Only callable by the administratorThe operator indexes must be in increasing order and contain no duplicateThe limit cannot exceed the total key count of the operatorThe _indexes and _newLimits must have the same length.Each limit value is applied to the operator index at the same index in the _indexes array.
Parameters
Name
Type
Description
_operatorIndexes
uint256[]
The operator indexes, in increasing order and duplicate free
_newLimits
uint32[]
The new staking limit of the operators
_snapshotBlock
uint256
The block number at which the snapshot was computed
setOperatorName
Changes the operator name
Only callable by the administrator or the operator
Parameters
Name
Type
Description
_index
uint256
The operator index
_newName
string
The new operator name
setOperatorStatus
Changes the operator status
Only callable by the administrator
Parameters
Name
Type
Description
_index
uint256
The operator index
_newStatus
bool
The new status of the operator
Events
AddedOperator
A new operator has been added to the registry
Parameters
Name
Type
Description
index indexed
uint256
The operator index
name
string
The operator display name
operatorAddress indexed
address
The operator address
AddedValidatorKeys
The operator or the admin added new validator keys and signatures
The public keys and signatures are concatenatedA public key is 48 bytes longA signature is 96 bytes long[P1, S1, P2, S2, ..., PN, SN] where N is the bytes length divided by (96 + 48)
Parameters
Name
Type
Description
index indexed
uint256
The operator index
publicKeysAndSignatures
bytes
The concatenated public keys and signatures
FundedValidatorKeys
A validator key got funded on the deposit contract. This event was introduced during a contract upgrade, in order to cover all possible public keys, this event will be replayed for past funded keys in order to have a complete coverage of all the funded public keys.In this particular scenario, the deferred value will be set to true, to indicate that we are not going to have the expected additional events and side effects in the same transaction (deposit to official DepositContract etc ...) because the event was synthetically crafted.
Parameters
Name
Type
Description
index indexed
uint256
The operator index
publicKeys
bytes[]
BLS Public key that got funded
deferred
bool
True if event has been replayed in the context of a migration
OperatorEditsAfterSnapshot
The operator edited its keys after the snapshot block
This means that we cannot assume that its key set is checked by the snapshotThis happens only if the limit was meant to be increased
Parameters
Name
Type
Description
index indexed
uint256
The operator index
currentLimit
uint256
The current operator limit
newLimit
uint256
The new operator limit that was attempted to be set
latestKeysEditBlockNumber indexed
uint256
The last block number at which the operator changed its keys
OperatorLimitUnchanged
The call didn't alter the limit of the operator
Parameters
Name
Type
Description
index indexed
uint256
The operator index
limit
uint256
The limit of the operator
RemovedValidatorKey
The operator or the admin removed a public key and its signature from the registry
Parameters
Name
Type
Description
index indexed
uint256
The operator index
publicKey
bytes
The BLS public key that has been removed
RequestedValidatorExits
The requested exit count has been updated
Parameters
Name
Type
Description
index indexed
uint256
The operator index
count
uint256
The count of requested exits
SetCurrentValidatorExitsDemand
The exit request demand has been updated
Parameters
Name
Type
Description
previousValidatorExitsDemand
uint256
The previous exit request demand
nextValidatorExitsDemand
uint256
The new exit request demand
SetOperatorAddress
The operator address has been changed
Parameters
Name
Type
Description
index indexed
uint256
The operator index
newOperatorAddress indexed
address
The new operator address
SetOperatorLimit
The operator limit has been changed
Parameters
Name
Type
Description
index indexed
uint256
The operator index
newLimit
uint256
The new operator staking limit
SetOperatorName
The operator display name has been changed
Parameters
Name
Type
Description
index indexed
uint256
The operator index
newName
string
The new display name
SetOperatorStatus
The operator status has been changed
Parameters
Name
Type
Description
index indexed
uint256
The operator index
active
bool
True if the operator is active
SetOperatorStoppedValidatorCount
The operator stopped validator count has been changed
Parameters
Name
Type
Description
index indexed
uint256
The operator index
newStoppedValidatorCount
uint256
The new stopped validator count
SetRiver
The stored river address has been changed
Parameters
Name
Type
Description
river indexed
address
The new river address
SetTotalValidatorExitsRequested
The total requested exit has been updated
Parameters
Name
Type
Description
previousTotalValidatorExitsRequested
uint256
The previous total requested exit
newTotalValidatorExitsRequested
uint256
The new total requested exit
UpdatedRequestedValidatorExitsUponStopped
The requested exit count has been update to fill the gap with the reported stopped count
Parameters
Name
Type
Description
index indexed
uint256
The operator index
oldRequestedExits
uint32
The old requested exit count
newRequestedExits
uint32
The new requested exit count
UpdatedStoppedValidators
The stopped validator array has been changedA validator is considered stopped if exiting, exited or slashedThis event is emitted when the oracle reports new stopped validators counts
Parameters
Name
Type
Description
stoppedValidatorCounts
uint32[]
The new stopped validator counts
Errors
InactiveOperator
The calling operator is inactive
Parameters
Name
Type
Description
index
uint256
The operator index
InvalidArrayLengths
The provided operator and limits array have different lengths
InvalidEmptyArray
The provided operator and limits array are empty
InvalidEmptyStoppedValidatorCountsArray
Thrown when an invalid empty stopped validator array is provided
InvalidFundedKeyDeletionAttempt
A funded key deletion has been attempted
InvalidIndexOutOfBounds
The index that is removed is out of bounds
InvalidKeyCount
The provided key count is 0
InvalidKeysLength
The provided concatenated keys do not have the expected length
InvalidStoppedValidatorCountsSum
Thrown when the sum of stopped validators is invalid
InvalidUnsortedIndexes
The index provided are not sorted properly (descending order)
NoExitRequestsToPerform
Thrown when no exit requests can be performed
OperatorLimitTooHigh
The value for the operator limit is too high
Parameters
Name
Type
Description
index
uint256
The operator index
limit
uint256
The new limit provided
keyCount
uint256
The operator key count
OperatorLimitTooLow
The value for the limit is too low
Parameters
Name
Type
Description
index
uint256
The operator index
limit
uint256
The new limit provided
fundedKeyCount
uint256
The operator funded key count
StoppedValidatorCountAboveFundedCount
The provided stopped validator count of an operator is above its funded validator count
Parameters
Name
Type
Description
operatorIndex
uint256
undefined
stoppedCount
uint32
undefined
fundedCount
uint32
undefined
StoppedValidatorCountArrayShrinking
The provided stopped validator count array is shrinking
StoppedValidatorCountsDecreased
Throw when an element in the stopped validator array is decreasing
StoppedValidatorCountsTooHigh
Thrown when the number of elements in the array is too high compared to operator count
UnorderedOperatorList
The provided list of operators is not in increasing order
function addOperator(string _name, address _operator) external nonpayable returns (uint256)
function addValidators(uint256 _index, uint32 _keyCount, bytes _publicKeysAndSignatures) external nonpayable
function demandValidatorExits(uint256 _count, uint256 _depositedValidatorCount) external nonpayable
function getCurrentValidatorExitsDemand() external view returns (uint256)
function getNextValidatorsToDepositFromActiveOperators(uint256 _count) external view returns (bytes[] publicKeys, bytes[] signatures)
function getOperator(uint256 _index) external view returns (struct OperatorsV2.Operator)
function getOperatorCount() external view returns (uint256)
function getOperatorStoppedValidatorCount(uint256 _idx) external view returns (uint32)
function getRiver() external view returns (address)
function getStoppedAndRequestedExitCounts() external view returns (uint32, uint256)
function getStoppedValidatorCountPerOperator() external view returns (uint32[])
function getTotalStoppedValidatorCount() external view returns (uint32)
function getTotalValidatorExitsRequested() external view returns (uint256)
This contract handles the list of operators and their keys
Methods
acceptAdmin
Accept the transfer of ownership
Only callable by the pending admin. Resets the pending admin if successful.
addOperator
Adds an operator to the registry
Only callable by the administrator
Parameters
Name
Type
Description
Returns
Name
Type
Description
addValidators
Adds new keys for an operator
Only callable by the administrator or the operator address
Parameters
Name
Type
Description
demandValidatorExits
Increases the exit request demand
This method is only callable by the river contract, and to actually forward the information to the node operators via event emission, the unprotected requestValidatorExits method must be called
Parameters
Name
Type
Description
forceFundedValidatorKeysEventEmission
Utility to force the broadcasting of events. Will keep its progress in storage to prevent being DoSed by the number of keys
Parameters
Name
Type
Description
getAdmin
Retrieves the current admin address
Returns
Name
Type
Description
getCurrentValidatorExitsDemand
Get the current exit request demand waiting to be triggeredThis value is the amount of exit requests that are demanded and not yet performed by the contract
Returns
Name
Type
Description
getNextValidatorsToDepositFromActiveOperators
Get the next validators that would be funded
Parameters
Name
Type
Description
Returns
Name
Type
Description
getOperator
Get operator details
Parameters
Name
Type
Description
Returns
Name
Type
Description
getOperatorCount
Get operator count
Returns
Name
Type
Description
getOperatorStoppedValidatorCount
Retrieve the stopped validator count for an operator index
Parameters
Name
Type
Description
Returns
Name
Type
Description
getPendingAdmin
Retrieve the current pending admin address
Returns
Name
Type
Description
getRiver
Retrieve the River address
Returns
Name
Type
Description
getStoppedAndRequestedExitCounts
Retrieve the total stopped and requested exit count
Returns
Name
Type
Description
getStoppedValidatorCountPerOperator
Retrieve the raw stopped validators array from storage
Returns
Name
Type
Description
getTotalStoppedValidatorCount
Retrieve the total stopped validator count
Returns
Name
Type
Description
getTotalValidatorExitsRequested
Retrieve the total requested exit countThis value is the amount of exit requests that have been performed, emitting an event for operators to catch
Returns
Name
Type
Description
getValidator
Get the details of a validator
Parameters
Name
Type
Description
Returns
Name
Type
Description
initOperatorsRegistryV1
Initializes the operators registry
Parameters
Name
Type
Description
initOperatorsRegistryV1_1
Initializes the operators registry for V1_1
listActiveOperators
Retrieve the active operator set
Returns
Name
Type
Description
pickNextValidatorsToDeposit
Retrieve validator keys based on operator statuses
Parameters
Name
Type
Description
Returns
Name
Type
Description
proposeAdmin
Proposes a new address as admin
This security prevents setting an invalid address as an admin. The pending admin has to claim its ownership of the contract, and prove that the new address is able to perform regular transactions.
Parameters
Name
Type
Description
removeValidators
Remove validator keys
Only callable by the administrator or the operator address. The indexes must be provided sorted in decreasing order and duplicate-free, otherwise the method will revert. The operator limit will be set to the lowest deleted key index if the operator's limit wasn't equal to its total key countThe operator or the admin cannot remove funded keysWhen removing validators, the indexes of specific unfunded keys can be changed in order to properly remove the keys from the storage array. Beware of this specific behavior when chaining calls as the targeted public key indexes can point to a different key after a first call was made and performed some swaps
Parameters
Name
Type
Description
reportStoppedValidatorCounts
Allows river to override the stopped validators arrayThis actions happens during the Oracle report processing
Parameters
Name
Type
Description
requestValidatorExits
Public endpoint to consume the exit request demand and perform the actual exit requestsThe selection algorithm will pick validators based on their active validator countsThis value is computed by using the count of funded keys and taking into account the stopped validator counts and exit requests
Parameters
Name
Type
Description
setOperatorAddress
Changes the operator address of an operator
Only callable by the administrator or the previous operator address
Parameters
Name
Type
Description
setOperatorLimits
Changes the operator staking limit
Only callable by the administratorThe operator indexes must be in increasing order and contain no duplicateThe limit cannot exceed the total key count of the operatorThe _indexes and _newLimits must have the same length.Each limit value is applied to the operator index at the same index in the _indexes array.
Parameters
Name
Type
Description
setOperatorName
Changes the operator name
Only callable by the administrator or the operator
Parameters
Name
Type
Description
setOperatorStatus
Changes the operator status
Only callable by the administrator
Parameters
Name
Type
Description
version
Retrieves the version of the contract
Returns
Name
Type
Description
Events
AddedOperator
A new operator has been added to the registry
Parameters
Name
Type
Description
AddedValidatorKeys
The operator or the admin added new validator keys and signatures
The public keys and signatures are concatenatedA public key is 48 bytes longA signature is 96 bytes long[P1, S1, P2, S2, ..., PN, SN] where N is the bytes length divided by (96 + 48)
Parameters
Name
Type
Description
FundedValidatorKeys
A validator key got funded on the deposit contract. This event was introduced during a contract upgrade, in order to cover all possible public keys, this event will be replayed for past funded keys in order to have a complete coverage of all the funded public keys. In this particular scenario, the deferred value will be set to true, to indicate that we are not going to have the expected additional events and side effects in the same transaction (deposit to official DepositContract etc ...) because the event was synthetically crafted.
Parameters
Name
Type
Description
Initialize
Emitted when the contract is properly initialized
Parameters
Name
Type
Description
OperatorEditsAfterSnapshot
The operator edited its keys after the snapshot block
This means that we cannot assume that its key set is checked by the snapshotThis happens only if the limit was meant to be increased
Parameters
Name
Type
Description
OperatorLimitUnchanged
The call didn't alter the limit of the operator
Parameters
Name
Type
Description
RemovedValidatorKey
The operator or the admin removed a public key and its signature from the registry
Parameters
Name
Type
Description
RequestedValidatorExits
The requested exit count has been updated
Parameters
Name
Type
Description
SetAdmin
The admin address changed
Parameters
Name
Type
Description
SetCurrentValidatorExitsDemand
The exit request demand has been updated
Parameters
Name
Type
Description
SetOperatorAddress
The operator address has been changed
Parameters
Name
Type
Description
SetOperatorLimit
The operator limit has been changed
Parameters
Name
Type
Description
SetOperatorName
The operator display name has been changed
Parameters
Name
Type
Description
SetOperatorStatus
The operator status has been changed
Parameters
Name
Type
Description
SetOperatorStoppedValidatorCount
The operator stopped validator count has been changed
Parameters
Name
Type
Description
SetPendingAdmin
The pending admin address changed
Parameters
Name
Type
Description
SetRiver
The stored river address has been changed
Parameters
Name
Type
Description
SetTotalValidatorExitsRequested
The total requested exit has been updated
Parameters
Name
Type
Description
UpdatedRequestedValidatorExitsUponStopped
The requested exit count has been update to fill the gap with the reported stopped count
Parameters
Name
Type
Description
UpdatedStoppedValidators
The stopped validator array has been changedA validator is considered stopped if exiting, exited or slashedThis event is emitted when the oracle reports new stopped validators counts
Parameters
Name
Type
Description
Errors
FundedKeyEventMigrationComplete
Emitted when the event rebroadcasting is done and we attempt to broadcast new events
InactiveOperator
The calling operator is inactive
Parameters
Name
Type
Description
InvalidArrayLengths
The provided operator and limits array have different lengths
InvalidEmptyArray
The provided operator and limits array are empty
InvalidEmptyStoppedValidatorCountsArray
Thrown when an invalid empty stopped validator array is provided
InvalidEmptyString
The string is empty
InvalidFundedKeyDeletionAttempt
A funded key deletion has been attempted
InvalidIndexOutOfBounds
The index that is removed is out of bounds
InvalidInitialization
An error occurred during the initialization
Parameters
Name
Type
Description
InvalidKeyCount
The provided key count is 0
InvalidKeysLength
The provided concatenated keys do not have the expected length
InvalidStoppedValidatorCountsSum
Thrown when the sum of stopped validators is invalid
InvalidUnsortedIndexes
The index provided are not sorted properly (descending order)
InvalidZeroAddress
The address is zero
NoExitRequestsToPerform
Thrown when no exit requests can be performed
OperatorLimitTooHigh
The value for the operator limit is too high
Parameters
Name
Type
Description
OperatorLimitTooLow
The value for the limit is too low
Parameters
Name
Type
Description
OperatorNotFound
The operator was not found
Parameters
Name
Type
Description
SliceOutOfBounds
The slice is outside of the initial bytes bounds
SliceOverflow
The length overflows an uint
StoppedValidatorCountAboveFundedCount
The provided stopped validator count of an operator is above its funded validator count
Parameters
Name
Type
Description
StoppedValidatorCountArrayShrinking
The provided stopped validator count array is shrinking
StoppedValidatorCountsDecreased
Throw when an element in the stopped validator array is decreasing
StoppedValidatorCountsTooHigh
Thrown when the number of elements in the array is too high compared to operator count
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
UnorderedOperatorList
The provided list of operators is not in increasing order
snapshotBlock indexed
uint256
The block number of the snapshot
_name
string
The name identifying the operator
_operator
address
The address representing the operator, receiving the rewards
_0
uint256
The index of the new operator
_index
uint256
The operator index
_keyCount
uint32
The amount of keys provided
_publicKeysAndSignatures
bytes
Public keys of the validator, concatenated
_count
uint256
The amount of exit requests to add to the demand
_depositedValidatorCount
uint256
The total deposited validator count
_amountToEmit
uint256
The amount of events to emit at maximum in this call
_0
address
The admin address
_0
uint256
The current exit request demand
_count
uint256
Count of validators that would be funded next
publicKeys
bytes[]
An array of fundable public keys
signatures
bytes[]
An array of signatures linked to the public keys
_index
uint256
The index of the operator
_0
OperatorsV2.Operator
The details of the operator
_0
uint256
The operator count
_idx
uint256
The index of the operator
_0
uint32
The stopped validator count of the operator
_0
address
The pending admin address
_0
address
The address of River
_0
uint32
The total stopped count
_1
uint256
The total requested exit count
_0
uint32[]
The stopped validator array
_0
uint32
The total stopped validator count
_0
uint256
The total requested exit count
_operatorIndex
uint256
The index of the operator
_validatorIndex
uint256
The index of the validator
publicKey
bytes
The public key of the validator
signature
bytes
The signature used during deposit
funded
bool
True if validator has been funded
_admin
address
Admin in charge of managing operators
_river
address
Address of River system
_0
OperatorsV2.Operator[]
The list of active operators and their details
_count
uint256
Max amount of keys requested
publicKeys
bytes[]
An array of public keys
signatures
bytes[]
An array of signatures linked to the public keys
_newAdmin
address
New admin address
_index
uint256
The operator index
_indexes
uint256[]
The indexes of the keys to remove
_stoppedValidatorCounts
uint32[]
The new stopped validators array
_depositedValidatorCount
uint256
The total deposited validator count
_count
uint256
Max amount of exits to request
_index
uint256
The operator index
_newOperatorAddress
address
The new address of the operator
_operatorIndexes
uint256[]
The operator indexes, in increasing order and duplicate free
_newLimits
uint32[]
The new staking limit of the operators
_snapshotBlock
uint256
The block number at which the snapshot was computed
_index
uint256
The operator index
_newName
string
The new operator name
_index
uint256
The operator index
_newStatus
bool
The new status of the operator
_0
string
Version of the contract
index indexed
uint256
The operator index
name
string
The operator display name
operatorAddress indexed
address
The operator address
index indexed
uint256
The operator index
publicKeysAndSignatures
bytes
The concatenated public keys and signatures
index indexed
uint256
The operator index
publicKeys
bytes[]
BLS Public key that got funded
deferred
bool
True if event has been replayed in the context of a migration
version
uint256
New version of the contracts
cdata
bytes
Complete calldata that was used during the initialization
index indexed
uint256
The operator index
currentLimit
uint256
The current operator limit
newLimit
uint256
The new operator limit that was attempted to be set
latestKeysEditBlockNumber indexed
uint256
The last block number at which the operator changed its keys
index indexed
uint256
The operator index
limit
uint256
The limit of the operator
index indexed
uint256
The operator index
publicKey
bytes
The BLS public key that has been removed
index indexed
uint256
The operator index
count
uint256
The count of requested exits
admin indexed
address
New admin address
previousValidatorExitsDemand
uint256
The previous exit request demand
nextValidatorExitsDemand
uint256
The new exit request demand
index indexed
uint256
The operator index
newOperatorAddress indexed
address
The new operator address
index indexed
uint256
The operator index
newLimit
uint256
The new operator staking limit
index indexed
uint256
The operator index
newName
string
The new display name
index indexed
uint256
The operator index
active
bool
True if the operator is active
index indexed
uint256
The operator index
newStoppedValidatorCount
uint256
The new stopped validator count
pendingAdmin indexed
address
New pending admin address
river indexed
address
The new river address
previousTotalValidatorExitsRequested
uint256
The previous total requested exit
newTotalValidatorExitsRequested
uint256
The new total requested exit
index indexed
uint256
The operator index
oldRequestedExits
uint32
The old requested exit count
newRequestedExits
uint32
The new requested exit count
stoppedValidatorCounts
uint32[]
The new stopped validator counts
index
uint256
The operator index
version
uint256
The version that was attempting to be initialized
expectedVersion
uint256
The version that was expected
index
uint256
The operator index
limit
uint256
The new limit provided
keyCount
uint256
The operator key count
index
uint256
The operator index
limit
uint256
The new limit provided
fundedKeyCount
uint256
The operator funded key count
index
uint256
The provided index
operatorIndex
uint256
undefined
stoppedCount
uint32
undefined
fundedCount
uint32
undefined
caller
address
Address performing the call
function acceptAdmin() external nonpayable
function addOperator(string _name, address _operator) external nonpayable returns (uint256)
function addValidators(uint256 _index, uint32 _keyCount, bytes _publicKeysAndSignatures) external nonpayable
function demandValidatorExits(uint256 _count, uint256 _depositedValidatorCount) external nonpayable
function forceFundedValidatorKeysEventEmission(uint256 _amountToEmit) external nonpayable
function getAdmin() external view returns (address)
function getCurrentValidatorExitsDemand() external view returns (uint256)
function getNextValidatorsToDepositFromActiveOperators(uint256 _count) external view returns (bytes[] publicKeys, bytes[] signatures)
function getOperator(uint256 _index) external view returns (struct OperatorsV2.Operator)
function getOperatorCount() external view returns (uint256)
function getOperatorStoppedValidatorCount(uint256 _idx) external view returns (uint32)
function getPendingAdmin() external view returns (address)
function getRiver() external view returns (address)
function getStoppedAndRequestedExitCounts() external view returns (uint32, uint256)
function getStoppedValidatorCountPerOperator() external view returns (uint32[])
function getTotalStoppedValidatorCount() external view returns (uint32)
function getTotalValidatorExitsRequested() external view returns (uint256)
The TLC token has a max supply of 1,000,000,000 and 18 decimal places.Upon deployment, all minted tokens are send to account provided at construction, in charge of creating the vesting schedulesThe contract is based on ERC20Votes by OpenZeppelin. Users need to delegate their voting power to someone or themselves to be able to vote.The contract contains vesting logics allowing vested users to still be able to delegate their voting power while their tokens are held in an escrow
Methods
CLOCK_MODE
Description of the clock
Returns
Name
Type
Description
DOMAIN_SEPARATOR
See {IERC20Permit-DOMAIN_SEPARATOR}.
Returns
Name
Type
Description
allowance
See {IERC20-allowance}.
Parameters
Name
Type
Description
Returns
Name
Type
Description
approve
See {IERC20-approve}. NOTE: If amount is the maximum uint256, the allowance is not updated on transferFrom. This is semantically equivalent to an infinite approval. Requirements: - spender cannot be the zero address.
Parameters
Name
Type
Description
Returns
Name
Type
Description
balanceOf
See {IERC20-balanceOf}.
Parameters
Name
Type
Description
Returns
Name
Type
Description
checkpoints
Get the pos-th checkpoint for account.
Parameters
Name
Type
Description
Returns
Name
Type
Description
clock
Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
Returns
Name
Type
Description
computeVestingReleasableAmount
Computes the releasable amount of tokens for a vesting schedule.
Parameters
Name
Type
Description
Returns
Name
Type
Description
computeVestingVestedAmount
Computes the vested amount of tokens for a vesting schedule.
Parameters
Name
Type
Description
Returns
Name
Type
Description
createVestingSchedule
Creates a new vesting scheduleThere may delay between the time a user should start vesting tokens and the time the vesting schedule is actually created on the contract.Typically a user joins the Liquid Collective but some weeks pass before the user gets all legal agreements in place and signed for the token grant emission to happen. In this case, the vesting schedule created for the token grant would start on the join date which is in the past.
As vesting schedules can be created in the past, this means that you should be careful when creating a vesting schedule and what duration parameters you use as this contract would allow creating a vesting schedule in the past and even a vesting schedule that has already ended.
Parameters
Name
Type
Description
Returns
Name
Type
Description
decimals
Returns the number of decimals used to get its user representation. For example, if decimals equals 2, a balance of 505 tokens should be displayed to a user as 5.05 (505 / 10 ** 2). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for display purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.
Returns
Name
Type
Description
decreaseAllowance
Atomically decreases the allowance granted to spender by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - spender cannot be the zero address. - spender must have allowance for the caller of at least subtractedValue.
Parameters
Name
Type
Description
Returns
Name
Type
Description
delegate
Delegate votes from the sender to delegatee.
Parameters
Name
Type
Description
delegateBySig
Delegates votes from signer to delegatee
Parameters
Name
Type
Description
delegateVestingEscrow
Delegate vesting escrowed tokens
Parameters
Name
Type
Description
Returns
Name
Type
Description
delegates
Get the address account is currently delegating to.
Parameters
Name
Type
Description
Returns
Name
Type
Description
eip712Domain
See {EIP-5267}. Available since v4.9.
Returns
Name
Type
Description
getPastTotalSupply
Retrieve the totalSupply at the end of timepoint. Note, this value is the sum of all balances. It is NOT the sum of all the delegated votes! Requirements: - timepoint must be in the past
Parameters
Name
Type
Description
Returns
Name
Type
Description
getPastVotes
Retrieve the number of votes for account at the end of timepoint. Requirements: - timepoint must be in the past
Parameters
Name
Type
Description
Returns
Name
Type
Description
getVestingSchedule
Get vesting schedule
The vesting schedule structure represents a static configuration used to compute the desired vesting details of a beneficiary at all times. The values won't change even after tokens are released.The only dynamic field of the structure is end, and is updated whenever a vesting schedule is revoked
Parameters
Name
Type
Description
Returns
Name
Type
Description
getVestingScheduleCount
Get count of vesting schedules
Returns
Name
Type
Description
getVotes
Gets the current votes balance for account
Parameters
Name
Type
Description
Returns
Name
Type
Description
increaseAllowance
Atomically increases the allowance granted to spender by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - spender cannot be the zero address.
Parameters
Name
Type
Description
Returns
Name
Type
Description
initTLCV1
Initializes the TLC Token
Parameters
Name
Type
Description
isGlobalUnlockedScheduleIgnored
Get vesting global unlock schedule activation status for a vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
migrateVestingSchedules
Migrates the vesting schedule state structures
name
Returns the name of the token.
Returns
Name
Type
Description
nonces
See {IERC20Permit-nonces}.
Parameters
Name
Type
Description
Returns
Name
Type
Description
numCheckpoints
Get number of checkpoints for account.
Parameters
Name
Type
Description
Returns
Name
Type
Description
permit
See {IERC20Permit-permit}.
Parameters
Name
Type
Description
releaseVestingSchedule
Release vesting scheduleWhen tokens are released from the escrow, the delegated address of the escrow will see its voting power decrease.The beneficiary has to make sure its delegation parameters are set properly to be able to use/delegate the voting power of its balance.
Parameters
Name
Type
Description
Returns
Name
Type
Description
revokeVestingSchedule
Revoke vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
symbol
Returns the symbol of the token, usually a shorter version of the name.
Returns
Name
Type
Description
totalSupply
See {IERC20-totalSupply}.
Returns
Name
Type
Description
transfer
See {IERC20-transfer}. Requirements: - to cannot be the zero address. - the caller must have a balance of at least amount.
Parameters
Name
Type
Description
Returns
Name
Type
Description
transferFrom
See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum uint256. Requirements: - from and to cannot be the zero address. - from must have a balance of at least amount. - the caller must have allowance for from's tokens of at least amount.
Parameters
Name
Type
Description
Returns
Name
Type
Description
vestingEscrow
Get the address of the escrow for a vesting schedule
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
Approval
Emitted when the allowance of a spender for an owner is set by a call to {approve}. value is the new allowance.
Parameters
Name
Type
Description
CreatedVestingSchedule
A new vesting schedule has been created
Parameters
Name
Type
Description
DelegateChanged
Emitted when an account changes their delegate.
Parameters
Name
Type
Description
DelegateVotesChanged
Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
Parameters
Name
Type
Description
DelegatedVestingEscrow
Vesting escrow has been delegated
Parameters
Name
Type
Description
EIP712DomainChanged
MAY be emitted to signal that the domain could have changed.
Initialized
Triggered when the contract has been initialized or reinitialized.
Parameters
Name
Type
Description
ReleasedVestingSchedule
Vesting schedule has been released
Parameters
Name
Type
Description
RevokedVestingSchedule
Vesting schedule has been revoked
Parameters
Name
Type
Description
Transfer
Emitted when value tokens are moved from one account (from) to another (to). Note that value may be zero.
Parameters
Name
Type
Description
Errors
GlobalUnlockUnderlfow
Underflow in global unlock logic (should never happen)
InvalidRevokedVestingScheduleEnd
Attempt to revoke a vesting schedule with an invalid end parameter
InvalidVestingScheduleParameter
Invalid parameter for a vesting schedule
Parameters
Name
Type
Description
InvalidZeroAddress
The address is zero
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
UnsufficientVestingScheduleCreatorBalance
Vesting schedule creator has unsufficient balance to create vesting schedule
VestingScheduleIsLocked
The vesting schedule is locked
VestingScheduleNotFound
The VestingSchedule was not found
Parameters
Name
Type
Description
VestingScheduleNotRevocable
The vesting schedule is not revocable
VestingScheduleNotRevocableInPast
Attempt to revoke a schedule in the past
ZeroReleasableAmount
No token to release
ERC20VestableVotesUpgradeableV1
Alluvial Finance Inc.
ERC20VestableVotesUpgradeableV1
This is an ERC20 extension that- can be used as source of vote power (inherited from OpenZeppelin ERC20VotesUpgradeable)- can delegate vote power from an account to another account (inherited from OpenZeppelin ERC20VotesUpgradeable)- can manage token vestings: ownership is progressively transferred to a beneficiary according to a vesting schedule- keeps a history (checkpoints) of each account's vote power@notice Notes from OpenZeppelin - vote power can be delegated either by calling the {delegate} function, or by providing a signature to be used with {delegateBySig}- keeps a history (checkpoints) of each account's vote power- power can be queried through the public accessors {getVotes} and {getPastVotes}.- by default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.@notice Notes about token vesting- any token holder can call the method {createVestingSchedule} in order to transfer tokens to a beneficiary according to a vesting schedule. When creating a vesting schedule, tokens are transferred to an escrow that holds the token while the vesting progresses. Voting power of the escrowed token is delegated to the beneficiary or a delegatee account set by the vesting schedule creator- the schedule beneficiary call {releaseVestingSchedule} to get vested tokens transferred from escrow- the schedule creator can revoke a revocable schedule by calling {revokeVestingSchedule} in which case the non-vested tokens are transferred from the escrow back to the creator- the schedule beneficiary can delegate escrow voting power to any account by calling {delegateVestingEscrow}@notice Vesting schedule attributes are- start : start time of the vesting period- cliff duration: duration before which first tokens gets ownable- total duration: duration of the entire vesting (sum of all vesting period durations)- period duration: duration of a single period of vesting- lock duration: duration before tokens gets unlocked. can exceed the duration of the vesting schedule- amount: amount of tokens granted by the vesting schedule- beneficiary: beneficiary of tokens after they are releaseVestingScheduled- revocable: whether the schedule can be revoked- ignoreGlobalUnlockSchedule: whether the schedule should ignore the global unlock schedule@notice Vesting schedule- if currentTime < cliff: vestedToken = 0- if cliff <= currentTime < end: vestedToken = (vestedPeriodCount(currentTime) _ periodDuration _ amount) / totalDuration- if end < currentTime: vestedToken = amount@notice Global unlock schedule- the global unlock schedule releases 1/24th of the total scheduled amount every month after the local lock end- the local lock end is the end of the lock period of the vesting schedule- the global unlock schedule is ignored if the vesting schedule has the ignoreGlobalUnlockSchedule flag set to true- the global unlock schedule is only a cap on the vested funds that can be withdrawn, it does not alter the vesting@notice Remark: After cliff new tokens get vested at the end of each period@notice Vested token & lock period- a vested token is a token that will be eventually releasable from the escrow to the beneficiary once the lock period is over- lock period prevents beneficiary from releasing vested tokens before the lock period ends. Vested tokens will eventually be releasable once the lock period is over@notice Example: Joe gets a vesting starting on Jan 1st 2022 with duration of 1 year and a lock period of 2 years.On Jan 1st 2023, Joe will have all tokens vested but can not yet release it due to the lock period.On Jan 1st 2024, lock period is over and Joe can release all tokens.
_lockDuration
uint32
duration during which tokens are locked (in seconds)
_revocable
bool
whether the vesting schedule is revocable or not
_amount
uint256
amount of token attributed by the vesting schedule
_beneficiary
address
address of the beneficiary of the tokens
_delegatee
address
address to delegate escrow voting power to
_ignoreGlobalUnlockSchedule
bool
whether the vesting schedule should ignore the global lock
r
bytes32
undefined
s
bytes32
undefined
verifyingContract
address
undefined
salt
bytes32
undefined
extensions
uint256[]
undefined
v
uint8
undefined
r
bytes32
undefined
s
bytes32
undefined
_0
string
undefined
_0
bytes32
undefined
owner
address
undefined
spender
address
undefined
_0
uint256
undefined
spender
address
undefined
amount
uint256
undefined
_0
bool
undefined
account
address
undefined
_0
uint256
undefined
account
address
undefined
pos
uint32
undefined
_0
ERC20VotesUpgradeable.Checkpoint
undefined
_0
uint48
undefined
_index
uint256
index of the vesting schedule
_0
uint256
amount of releasable tokens
_index
uint256
index of the vesting schedule
_0
uint256
amount of vested tokens
_start
uint64
start time of the vesting
_cliffDuration
uint32
duration to vesting cliff (in seconds)
_duration
uint32
total vesting schedule duration after which all tokens are vested (in seconds)
_periodDuration
uint32
_0
uint256
index of the created vesting schedule
_0
uint8
undefined
spender
address
undefined
subtractedValue
uint256
undefined
_0
bool
undefined
delegatee
address
undefined
delegatee
address
undefined
nonce
uint256
undefined
expiry
uint256
undefined
v
uint8
_index
uint256
index of the vesting schedule
_delegatee
address
address to delegate the token to
_0
bool
True on success
account
address
undefined
_0
address
undefined
fields
bytes1
undefined
name
string
undefined
version
string
undefined
chainId
uint256
timepoint
uint256
undefined
_0
uint256
undefined
account
address
undefined
timepoint
uint256
undefined
_0
uint256
undefined
_index
uint256
Index of the vesting schedule
_0
VestingSchedulesV2.VestingSchedule
undefined
_0
uint256
count of vesting schedules
account
address
undefined
_0
uint256
undefined
spender
address
undefined
addedValue
uint256
undefined
_0
bool
undefined
_account
address
The initial account to grant all the minted tokens
_index
uint256
Index of the vesting schedule
_0
bool
true if the vesting schedule should ignore the global unlock schedule
_0
string
undefined
owner
address
undefined
_0
uint256
undefined
account
address
undefined
_0
uint32
undefined
owner
address
undefined
spender
address
undefined
value
uint256
undefined
deadline
uint256
_index
uint256
Index of the vesting schedule to release
_0
uint256
released amount
_index
uint256
Index of the vesting schedule to revoke
_end
uint64
End date for the schedule
_0
uint256
amount returned to the vesting schedule creator
_0
string
undefined
_0
uint256
undefined
to
address
undefined
amount
uint256
undefined
_0
bool
undefined
from
address
undefined
to
address
undefined
amount
uint256
undefined
_0
bool
undefined
_index
uint256
Index of the vesting schedule
_0
address
address of the escrow
owner indexed
address
undefined
spender indexed
address
undefined
value
uint256
undefined
index
uint256
Vesting schedule index
creator indexed
address
Creator of the vesting schedule
beneficiary indexed
address
Vesting beneficiary address
amount
uint256
delegator indexed
address
undefined
fromDelegate indexed
address
undefined
toDelegate indexed
address
undefined
delegate indexed
address
undefined
previousBalance
uint256
undefined
newBalance
uint256
undefined
index
uint256
Vesting schedule index
oldDelegatee indexed
address
old delegatee
newDelegatee indexed
address
new delegatee
beneficiary indexed
address
version
uint8
undefined
index
uint256
Vesting schedule index
releasedAmount
uint256
Amount of tokens released to the beneficiary
index
uint256
Vesting schedule index
returnedAmount
uint256
Amount of tokens returned to the creator
newEnd
uint256
New end timestamp after revoke action
from indexed
address
undefined
to indexed
address
undefined
value
uint256
undefined
msg
string
undefined
caller
address
Address performing the call
index
uint256
vesting schedule index
duration of a period after which new tokens unlock (in seconds)
undefined
undefined
undefined
Vesting schedule amount
vesting schedule beneficiary
function CLOCK_MODE() external view returns (string)
function DOMAIN_SEPARATOR() external view returns (bytes32)
function allowance(address owner, address spender) external view returns (uint256)
function approve(address spender, uint256 amount) external nonpayable returns (bool)
function balanceOf(address account) external view returns (uint256)
function checkpoints(address account, uint32 pos) external view returns (struct ERC20VotesUpgradeable.Checkpoint)
function clock() external view returns (uint48)
function computeVestingReleasableAmount(uint256 _index) external view returns (uint256)
function computeVestingVestedAmount(uint256 _index) external view returns (uint256)
event Transfer(address indexed from, address indexed to, uint256 value)
error GlobalUnlockUnderlfow()
error InvalidRevokedVestingScheduleEnd()
error InvalidVestingScheduleParameter(string msg)
error InvalidZeroAddress()
error Unauthorized(address caller)
error UnsufficientVestingScheduleCreatorBalance()
error VestingScheduleIsLocked()
error VestingScheduleNotFound(uint256 index)
error VestingScheduleNotRevocable()
error VestingScheduleNotRevocableInPast()
error ZeroReleasableAmount()
Methods
CLOCK_MODE
Description of the clock
Returns
Name
Type
Description
_0
string
undefined
DOMAIN_SEPARATOR
See {IERC20Permit-DOMAIN_SEPARATOR}.
Returns
Name
Type
Description
_0
bytes32
undefined
allowance
See {IERC20-allowance}.
Parameters
Name
Type
Description
owner
address
undefined
spender
address
undefined
Returns
Name
Type
Description
_0
uint256
undefined
approve
See {IERC20-approve}. NOTE: If amount is the maximum uint256, the allowance is not updated on transferFrom. This is semantically equivalent to an infinite approval. Requirements: - spender cannot be the zero address.
Parameters
Name
Type
Description
spender
address
undefined
amount
uint256
undefined
Returns
Name
Type
Description
_0
bool
undefined
balanceOf
See {IERC20-balanceOf}.
Parameters
Name
Type
Description
account
address
undefined
Returns
Name
Type
Description
_0
uint256
undefined
checkpoints
Get the pos-th checkpoint for account.
Parameters
Name
Type
Description
account
address
undefined
pos
uint32
undefined
Returns
Name
Type
Description
_0
ERC20VotesUpgradeable.Checkpoint
undefined
clock
Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
Returns
Name
Type
Description
_0
uint48
undefined
computeVestingReleasableAmount
Computes the releasable amount of tokens for a vesting schedule.
Parameters
Name
Type
Description
_index
uint256
index of the vesting schedule
Returns
Name
Type
Description
_0
uint256
amount of releasable tokens
computeVestingVestedAmount
Computes the vested amount of tokens for a vesting schedule.
Parameters
Name
Type
Description
_index
uint256
index of the vesting schedule
Returns
Name
Type
Description
_0
uint256
amount of vested tokens
createVestingSchedule
Creates a new vesting scheduleThere may delay between the time a user should start vesting tokens and the time the vesting schedule is actually created on the contract.Typically a user joins the Liquid Collective but some weeks pass before the user gets all legal agreements in place and signed for the token grant emission to happen. In this case, the vesting schedule created for the token grant would start on the join date which is in the past.
As vesting schedules can be created in the past, this means that you should be careful when creating a vesting schedule and what duration parameters you use as this contract would allow creating a vesting schedule in the past and even a vesting schedule that has already ended.
Parameters
Name
Type
Description
_start
uint64
start time of the vesting
_cliffDuration
uint32
duration to vesting cliff (in seconds)
_duration
uint32
total vesting schedule duration after which all tokens are vested (in seconds)
_periodDuration
uint32
Returns
Name
Type
Description
_0
uint256
index of the created vesting schedule
decimals
Returns the number of decimals used to get its user representation. For example, if decimals equals 2, a balance of 505 tokens should be displayed to a user as 5.05 (505 / 10 ** 2). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for display purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.
Returns
Name
Type
Description
_0
uint8
undefined
decreaseAllowance
Atomically decreases the allowance granted to spender by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - spender cannot be the zero address. - spender must have allowance for the caller of at least subtractedValue.
Parameters
Name
Type
Description
spender
address
undefined
subtractedValue
uint256
undefined
Returns
Name
Type
Description
_0
bool
undefined
delegate
Delegate votes from the sender to delegatee.
Parameters
Name
Type
Description
delegatee
address
undefined
delegateBySig
Delegates votes from signer to delegatee
Parameters
Name
Type
Description
delegatee
address
undefined
nonce
uint256
undefined
expiry
uint256
undefined
v
uint8
delegateVestingEscrow
Delegate vesting escrowed tokens
Parameters
Name
Type
Description
_index
uint256
index of the vesting schedule
_delegatee
address
address to delegate the token to
Returns
Name
Type
Description
_0
bool
True on success
delegates
Get the address account is currently delegating to.
Parameters
Name
Type
Description
account
address
undefined
Returns
Name
Type
Description
_0
address
undefined
eip712Domain
See {EIP-5267}. Available since v4.9.
Returns
Name
Type
Description
fields
bytes1
undefined
name
string
undefined
version
string
undefined
chainId
uint256
undefined
getPastTotalSupply
Retrieve the totalSupply at the end of timepoint. Note, this value is the sum of all balances. It is NOT the sum of all the delegated votes! Requirements: - timepoint must be in the past
Parameters
Name
Type
Description
timepoint
uint256
undefined
Returns
Name
Type
Description
_0
uint256
undefined
getPastVotes
Retrieve the number of votes for account at the end of timepoint. Requirements: - timepoint must be in the past
Parameters
Name
Type
Description
account
address
undefined
timepoint
uint256
undefined
Returns
Name
Type
Description
_0
uint256
undefined
getVestingSchedule
Get vesting schedule
The vesting schedule structure represents a static configuration used to compute the desired vesting details of a beneficiary at all times. The values won't change even after tokens are released.The only dynamic field of the structure is end, and is updated whenever a vesting schedule is revoked
Parameters
Name
Type
Description
_index
uint256
Index of the vesting schedule
Returns
Name
Type
Description
_0
VestingSchedulesV2.VestingSchedule
undefined
getVestingScheduleCount
Get count of vesting schedules
Returns
Name
Type
Description
_0
uint256
count of vesting schedules
getVotes
Gets the current votes balance for account
Parameters
Name
Type
Description
account
address
undefined
Returns
Name
Type
Description
_0
uint256
undefined
increaseAllowance
Atomically increases the allowance granted to spender by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - spender cannot be the zero address.
Parameters
Name
Type
Description
spender
address
undefined
addedValue
uint256
undefined
Returns
Name
Type
Description
_0
bool
undefined
isGlobalUnlockedScheduleIgnored
Get vesting global unlock schedule activation status for a vesting schedule
Parameters
Name
Type
Description
_index
uint256
Index of the vesting schedule
Returns
Name
Type
Description
_0
bool
true if the vesting schedule should ignore the global unlock schedule
name
Returns the name of the token.
Returns
Name
Type
Description
_0
string
undefined
nonces
See {IERC20Permit-nonces}.
Parameters
Name
Type
Description
owner
address
undefined
Returns
Name
Type
Description
_0
uint256
undefined
numCheckpoints
Get number of checkpoints for account.
Parameters
Name
Type
Description
account
address
undefined
Returns
Name
Type
Description
_0
uint32
undefined
permit
See {IERC20Permit-permit}.
Parameters
Name
Type
Description
owner
address
undefined
spender
address
undefined
value
uint256
undefined
deadline
uint256
releaseVestingSchedule
Release vesting scheduleWhen tokens are released from the escrow, the delegated address of the escrow will see its voting power decrease.The beneficiary has to make sure its delegation parameters are set properly to be able to use/delegate the voting power of its balance.
Parameters
Name
Type
Description
_index
uint256
Index of the vesting schedule to release
Returns
Name
Type
Description
_0
uint256
released amount
revokeVestingSchedule
Revoke vesting schedule
Parameters
Name
Type
Description
_index
uint256
Index of the vesting schedule to revoke
_end
uint64
End date for the schedule
Returns
Name
Type
Description
_0
uint256
amount returned to the vesting schedule creator
symbol
Returns the symbol of the token, usually a shorter version of the name.
Returns
Name
Type
Description
_0
string
undefined
totalSupply
See {IERC20-totalSupply}.
Returns
Name
Type
Description
_0
uint256
undefined
transfer
See {IERC20-transfer}. Requirements: - to cannot be the zero address. - the caller must have a balance of at least amount.
Parameters
Name
Type
Description
to
address
undefined
amount
uint256
undefined
Returns
Name
Type
Description
_0
bool
undefined
transferFrom
See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum uint256. Requirements: - from and to cannot be the zero address. - from must have a balance of at least amount. - the caller must have allowance for from's tokens of at least amount.
Parameters
Name
Type
Description
from
address
undefined
to
address
undefined
amount
uint256
undefined
Returns
Name
Type
Description
_0
bool
undefined
vestingEscrow
Get the address of the escrow for a vesting schedule
Parameters
Name
Type
Description
_index
uint256
Index of the vesting schedule
Returns
Name
Type
Description
_0
address
address of the escrow
Events
Approval
Emitted when the allowance of a spender for an owner is set by a call to {approve}. value is the new allowance.
Parameters
Name
Type
Description
owner indexed
address
undefined
spender indexed
address
undefined
value
uint256
undefined
CreatedVestingSchedule
A new vesting schedule has been created
Parameters
Name
Type
Description
index
uint256
Vesting schedule index
creator indexed
address
Creator of the vesting schedule
beneficiary indexed
address
Vesting beneficiary address
amount
uint256
DelegateChanged
Emitted when an account changes their delegate.
Parameters
Name
Type
Description
delegator indexed
address
undefined
fromDelegate indexed
address
undefined
toDelegate indexed
address
undefined
DelegateVotesChanged
Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
Parameters
Name
Type
Description
delegate indexed
address
undefined
previousBalance
uint256
undefined
newBalance
uint256
undefined
DelegatedVestingEscrow
Vesting escrow has been delegated
Parameters
Name
Type
Description
index
uint256
Vesting schedule index
oldDelegatee indexed
address
old delegatee
newDelegatee indexed
address
new delegatee
beneficiary indexed
address
vesting schedule beneficiary
EIP712DomainChanged
MAY be emitted to signal that the domain could have changed.
Initialized
Triggered when the contract has been initialized or reinitialized.
Parameters
Name
Type
Description
version
uint8
undefined
ReleasedVestingSchedule
Vesting schedule has been released
Parameters
Name
Type
Description
index
uint256
Vesting schedule index
releasedAmount
uint256
Amount of tokens released to the beneficiary
RevokedVestingSchedule
Vesting schedule has been revoked
Parameters
Name
Type
Description
index
uint256
Vesting schedule index
returnedAmount
uint256
Amount of tokens returned to the creator
newEnd
uint256
New end timestamp after revoke action
Transfer
Emitted when value tokens are moved from one account (from) to another (to). Note that value may be zero.
Parameters
Name
Type
Description
from indexed
address
undefined
to indexed
address
undefined
value
uint256
undefined
Errors
GlobalUnlockUnderlfow
Underflow in global unlock logic (should never happen)
InvalidRevokedVestingScheduleEnd
Attempt to revoke a vesting schedule with an invalid end parameter
InvalidVestingScheduleParameter
Invalid parameter for a vesting schedule
Parameters
Name
Type
Description
msg
string
undefined
Unauthorized
The operator is unauthorized for the caller
Parameters
Name
Type
Description
caller
address
Address performing the call
UnsufficientVestingScheduleCreatorBalance
Vesting schedule creator has unsufficient balance to create vesting schedule
Get the deposited validator count (the count of deposits made by the contract)
Returns
Name
Type
Description
_0
uint256
The deposited validator count
getELFeeRecipient
Retrieve the execution layer fee recipient
Returns
Name
Type
Description
_0
address
The execution layer fee recipient address
getExpectedEpochId
Retrieve expected epoch id
Returns
Name
Type
Description
_0
uint256
The current expected epoch id
getFrameFirstEpochId
Retrieve the first epoch id of the frame of the provided epoch id
Parameters
Name
Type
Description
_epochId
uint256
Epoch id used to get the frame
Returns
Name
Type
Description
_0
uint256
The first epoch id of the frame containing the given epoch id
getGlobalFee
Get the current global fee
Returns
Name
Type
Description
_0
uint256
The global fee
getKeeper
Get the keeper address
Returns
Name
Type
Description
_0
address
The keeper address
getLastCompletedEpochId
Retrieve the last completed epoch id
Returns
Name
Type
Description
_0
uint256
The last completed epoch id
getLastConsensusLayerReport
Retrieve the last consensus layer report
Returns
Name
Type
Description
_0
IOracleManagerV1.StoredConsensusLayerReport
The stored consensus layer report
getMetadataURI
Retrieve the metadata uri string value
Returns
Name
Type
Description
_0
string
The metadata uri string value
getOperatorsRegistry
Retrieve the operators registry
Returns
Name
Type
Description
_0
address
The operators registry address
getOracle
Get oracle address
Returns
Name
Type
Description
_0
address
The oracle address
getPendingAdmin
Retrieve the current pending admin address
Returns
Name
Type
Description
_0
address
The pending admin address
getRedeemManager
Retrieve the redeem manager
Returns
Name
Type
Description
_0
address
The redeem manager address
getReportBounds
Retrieve the report bounds
Returns
Name
Type
Description
_0
ReportBounds.ReportBoundsStruct
The report bounds
getTime
Retrieve the block timestamp
Returns
Name
Type
Description
_0
uint256
The current timestamp from the EVM context
getWithdrawalCredentials
Retrieve the withdrawal credentials
Returns
Name
Type
Description
_0
bytes32
The withdrawal credentials
increaseAllowance
Increase allowance to another account
Parameters
Name
Type
Description
_spender
address
Spender that receives the allowance
_additionalValue
uint256
Amount of shares to add
Returns
Name
Type
Description
_0
bool
True if success
initRiverV1
Initializes the River system
Parameters
Name
Type
Description
_depositContractAddress
address
Address to make Consensus Layer deposits
_elFeeRecipientAddress
address
Address that receives the execution layer fees
_withdrawalCredentials
bytes32
Credentials to use for every validator deposit
_oracleAddress
address
initRiverV1_1
Initialized version 1.1 of the River System
Parameters
Name
Type
Description
_redeemManager
address
The redeem manager address
_epochsPerFrame
uint64
The amounts of epochs in a frame
_slotsPerEpoch
uint64
The slots inside an epoch
_secondsPerSlot
uint64
initRiverV1_2
Initializes version 1.2 of the River System
isValidEpoch
Verifies if the provided epoch is valid
Parameters
Name
Type
Description
_epoch
uint256
undefined
Returns
Name
Type
Description
_0
bool
True if valid
name
Retrieve the token name
Returns
Name
Type
Description
_0
string
The token name
proposeAdmin
Proposes a new address as admin
This security prevents setting an invalid address as an admin. The pending admin has to claim its ownership of the contract, and prove that the new address is able to perform regular transactions.
Parameters
Name
Type
Description
_newAdmin
address
New admin address
requestRedeem
Performs a redeem request on the redeem manager
Parameters
Name
Type
Description
_lsETHAmount
uint256
The amount of LsETH to redeem
_recipient
address
The address that will own the redeem request
Returns
Name
Type
Description
_redeemRequestId
uint32
The ID of the newly created redeem request
resolveRedeemRequests
Resolves the provided redeem requests by calling the redeem manager
Parameters
Name
Type
Description
_redeemRequestIds
uint32[]
The list of redeem requests to resolve
Returns
Name
Type
Description
withdrawalEventIds
int64[]
The list of matching withdrawal events, or error codes
sendCLFunds
Input for consensus layer funds, containing both exit and skimming