or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Do you want to remove this version name and description?
Syncing
xxxxxxxxxx
Lido V2 on Goerli: a note for integrations
On March 24, Lido protocol on Goerli testnet has been successfully upgraded to V2.
This document is intended for Lido's existing partners and developers looking to understand the scope of the upgrade in terms of how their product interacts with Lido protocol. A high-level upgrade overview can be found in the blog post.
The code of the upgrade is open and available on Lido's GitHub. You can find all the changes in this PR.
The addresses of all the contracts deployed on Goerli are listed on the Lido's docs hub.
Lido UI has also been upgraded to V2 and is now being tested at https://stake.testnet.fi/
Deposit flow
No changes has been done to the deposit flow. All the addresses, calls, methods and events remain the same as before the protocol upgrade.
Subgraph and Reward History
Subgraph and Reward History on Goerli are not operational at the moment. The issue is being addressed, we expect the services to resume by end of April.
stETH shares
Shares mechanics explained in our integration guide remain the same as before the protocol upgrade.
Withdrawal flow
The biggest highlight of the upgrade is enabling withdrawals. The withdrawal flow is quite different from the deposit flow, unlike deposit flow, it is also async.
The process consists of the following steps:
Request size should be at least 100 wei (in stETH) and at most 1000 stETH. Larger amounts should be withdrawn in multiple requests, which can be batched via in-protocol API. Once requested, withdrawal cannot be canceled. The withdrawal NFT can be transferred to a different address, and the new owner will be able to claim the requested withdrawal once finalized.
The amount of claimable ETH is determined once the withdrawal request is finalised. The rate stETH/ETH of the request finalisation can't get higher than it's been at the moment of request creation. the user will be able to claim:
OR
The second option is unlikely, and we haven't ever seen the conditions for it on mainnet so far.
See the detailed description of the withdrawal flow below.
The end-user contract to deal with the withdrawals is
WithdrawalQueueERC721.sol
, which implements the ERC721 standard. NFT represents the position in the withdrawal queue and may be claimed after finalization of the request.The overview of the most frequent operations around the NFT queue.
Get the NFTs owned by the user (the not yet claimed ones)
getWithdrawalRequests(address _owner)
will return an array of NFT ids.Get NFT asset metadata
tokenURI(uint256)
as declared via ERC721 (Returns empty string currently. Subject to change in the future.)Init withdrawal
stETH
requestWithdrawalsWithPermit(uint256[] calldata amounts, address _owner, PermitInput calldata _permit)
and get the ids of created positions, wheremsg.sender
will be used to transfer tokens from and the_owner
will be the address that can claim or transfer NFT (defaults tomsg.sender
if it’s not provided.WithdrawalQueueERC721.sol
contract can be approved in a separate upfront transaction (stETH.approve(withdrawalQueueERC712.address, allowance)
), and therequestWithdrawals(uint256[] calldata amounts, address _owner)
method called afterwards.wstETH
requestWithdrawalsWstETHWithPermit(uint256[] calldata amounts, address _owner, PermitInput calldata _permit)
and get the ids of created positions, wheremsg.sender
will be used to transfer tokens from, and the_owner
will be the address that can claim or transfer NFT (defaults tomsg.sender
if it’s not provided.WithdrawalQueueERC721.sol
contract can be approved in a separate upfront transaction (wstETH.approve(withdrawalQueueERC712.address, allowance)
), and therequestWithdrawalsWstETH(uint256[] calldata amounts, address _owner)
method called afterwards.PermitInput
structure defined as follows:Get withdrawal request status (statuses refresh every ~4 hours on Goerli and once a day on mainnet)
getWithdrawalStatus(uint256[] calldata _requestIds)
with ids of the user's positions and get the amount of stETH from the returned struct.Claim user's ETH
claimWithdrawal(uint256)
with the NFT Id on behalf of the NFT owner.It is also possible to claim withdrawals in batches, it's being done in two steps:
claimWithdrawals(uint256[] calldata _requestIDs, hints)
wherefindCheckpointHints(uint256[] calldata _requestIDs, 1, lastCheckpoint)
getLastCheckpointIndex()
There is an unlikely scenario of Lido protocol going into bunker mode in case of Lido's validators getting slashed. This will result in the withdrawals processing becoming significantly slower, but it isn't meant to interfere with any specific withdrawal flow elements. However, the amount of ETH claimed in this case might be lower than the amount requested in stETH.
The full withdrawal flow is expected to take from a few hours on Goerli or a single day on mainnet to up to several weeks (in case of the bunker mode on). In other words, the request finalization can't happen earlier than on the next Accounting Oracle report, but will take longer if there's not enough ETH in EL buffers, and validator exits will be triggered.
How to get APR
Lido on Ethereum V2 employs not one, but two Oracles: Accounting Oracle & Exit Bus. Former provides rebase data & finalizes withdrawal request, the latter — determines which validators to ask for exiting.
In order to retain backwards compatibility, original Lido Oracle contract is updated & renamed to Legacy Oracle. The data is updated, but the contract is deprecated and would be removed in the upgrades following V2.
Although the old way of calculating the APR would still result in relevant numbers, the math might be off in case of significant withdrawals.
How it was
How it is
New proper way:
from
[1]
:To calculated APR for the last completed oracle frame:
So, the new formula takes into account
preTotalShares
andpostTotalShares
values, while, in contrast, the old formula didn't use them:The new formula also doesn't require to calculate
lidoFee
at all (because fee distribution works by changing total shares amount under the hood).Why does it matter
When Lido V2 protocol finalizes withdrawal requests, the
Lido
contract sends ether toWithdrawalQueue
(excluding these funds fromtotalPooledEther
, i.e., decreasing TVL) and assigns to burn underlying locked requests'stETH
shares in return.In other words, withdrawal finalization decreases both TVL and total shares.
Old formula isn't suitable anymore because it catches TVL changes, but skips total shares changes.
Illustrative example (using smallish numbers far from the real ones for simplicity):
APR shown on the Lido's UIs
Please note that the APR shown on Lido's UI is not expected to match the APR calculated on-chain. The one displayed on our websites is a 7-days rolling average APR.
Other notable changes
permit
function as introduced in the EIP-2621: https://github.com/lidofinance/lido-dao/blob/feature/shapella-upgrade/contracts/0.4.24/StETHPermit.sol#L99-L112In other words, users can provide allowance for stETH using the off-chain generated EIP-712 compatible signatures
isValidSignature(hash, signature)
function as introduced in the EIP-1271: https://github.com/lidofinance/lido-dao/blob/feature/shapella-upgrade/contracts/common/lib/SignatureUtils.sol#L29-L57transferSharesFrom
method has been added for stETH (had onlytransferShares
before) working within the provided allowance.