User can request to exit their staked position anytime.
It’s important to note that all staked positions are 100% collateralized, with ETH primarily held in active validators. Any remaining ETH may be in the operator pool, awaiting deposit into new validators.
Exiting a validator to access the underlying 32 ETH is not instantaneous; it requires the validator to go through the protocol's exit process and enter an exit queue. Consequently, a user exiting their staked position involves a two-step process:
Requesting exit: Users first signal their intent to exit by interacting with the integration contract, which locks their receipt tokens and places them in the exit queue of the operator pool contract. Each pool has its own exit queue, and an integration contract can be linked to multiple operator pools.
Receiving an exit ticket: A ticket, representing the user's position in the exit queue, is minted as an NFT. This ticket reflects the user's place in the queue until their ETH are available to withdraw.
Under normal conditions, with the pool generating rewards and receiving new deposits, it generally takes about 1-4 days for exited ETH to become available for withdrawal. However, in cases where exit demand significantly exceeds the available ETH, the process may be delayed. This delay is influenced by the Ethereum validator exit and withdrawal queue, which typically takes several days but can extend significantly longer in extreme cases.
When the pooling contract receives ETH to fulfill exit requests, it creates a 'cask' that corresponds to the received ETH and the current exit queue demand.
The exit queue functions as a system where users receive a ticket to retrieve their ETH. This ETH is periodically allocated to the queue in the form of casks. The queue operates on a first-come, first-served basis, without discrimination or favoritism towards any user or scenario.
When casks arrive, users must still claim their ETH. This is due to Solidity's limitations on the number of actions that can be performed in a single transaction. Consequently, a cask may fulfill one or multiple tickets at once. The smart contract cannot iterate through all tickets in a single transaction due to the potentially high and variable number of tickets.
Tickets can have several statuses:
unfulfillable
: the ticket is waiting for a cask to arrive and fulfill its exit request.
partially fulfillable
: the ticket has one or several casks partially fulfilling its exit request, this means that the ticket can be claimed, but this action will result in getting an updated ticket with the remaining amount yet to be claimed.
fulfillable
: the ticket has one or several casks completely fulfilling its exit request. Claiming this ticket will retrieve the funds and burn the ticket.
In the example above, we can see that:
Tickets #0
and #1
are currently fulfillable
by cask #0
.
Ticket #2
is currently partially fulfillable
by cask #1
Ticket #3
is unfulfillable
.
Keep in mind that both of these queues can grow independently, and the goal of the pooling contract is to provide casks to make the cask queue grow and reach the same height as the ticket queue, making all ticket fulfillable
When a user stakes, their position proportionally increases in value as staking rewards are generated by the operator pool validators.
Users deploy ETH through the partner's integration smart contract, which then forwards the ETH to one or multiple operator pools, depending on the configuration. This approach offers flexibility in structuring staking offerings, such as:
A single node operator with a 15% end-user fee.
Three operators with a 10/40/50% allocation and a total 17% end-user fee.
During the staking transaction, the user receives a receipt token representing their staked position within the integration contract. The integration contract, in turn, holds a proportional stake in the Node Operator Pool, based on the amount of ETH deployed through it.
The user's receipt tokens can be either soulbound or transferable (e.g., cToken or aToken), depending on the partner's choice during contract setup. The value of staked positions is determined by the underlying value of the operator pool, with an internal exchange rate that updates daily to reflect validator rewards. This exchange rate is purely technical and used exclusively between the smart contracts.
Staking fees are automatically calculated by the smart contracts based on the rewards generated, ensuring a seamless experience for the end user, who only deals with net values.
The Operator Pool requires offchain information to update pooling metrics like Operator Pool value and exchange rate, to take into account rewards generated by the pool validators.
This data is called an oracle report and is submitted by whitelisted Oracles to the Operator Pool smart contract, once every 24 hours. If all the Oracle quorum agrees on the same report, this one is processed by the Operator pool.
This means that user position values, and exit requests are processed on a 24 hours basis if oracles generate valid reports.
An oracle report consists of data like total ETH staked, total ETH currently in the protocol Exit Queue, total validators staked, total validators exited and strategy inputs to tell the pool to either accelerate user exits time or increase new validator deposits.
Using this data, Operator pool will perform multiple state transitions to:
deposit new validators
answer the exit demand in the exit queue
compute relevant staking fees
update the Operator pool exchange rate to take into account new rewards
exit validators if needed to match the user exit demand in the pool exit queue
You can find the report data and all Operator Pool metrics on our dune dashboard.