Address Contract Verified
Address
0x679D4C1cC6855C57726BEA1784F578315d6431f6
Balance
0 ETH
Nonce
1
Code Size
8525 bytes
Creator
0xeB658c4E...b3A3 at tx 0x7f491bb4...09960d
Indexed Transactions
0
Contract Bytecode
8525 bytes
0x6080604052600436106101bc575f3560e01c806375421af3116100f2578063c00f60c411610092578063db2296cd11610062578063db2296cd146104c1578063e00bfe50146104dd578063eea94dab146104fc578063fd92bff214610510575f80fd5b8063c00f60c414610472578063caa648b414610486578063d0e30db01461049a578063d9fb643a146104a2575f80fd5b80639e354677116100cd5780639e354677146103f4578063ab033ea914610413578063ac33a27314610432578063b9a5e71914610453575f80fd5b806375421af3146103885780637ca9c0f9146103b157806383b39e23146103d3575f80fd5b80632e1a7d4d1161015d57806352efea6e1161013857806352efea6e146103235780635aa6e675146103375780636c23ab4c14610355578063709d039d14610369575f80fd5b80632e1a7d4d1461029a578063481c6a75146102b95780634aa4a4fc14610304575f80fd5b80630d25a957116101985780630d25a95714610223578063162275f4146102375780631b63a9ec1461024b5780631c2ca2fd14610277575f80fd5b80621a5597146101c757806303f112e5146101ee57806306fdde0314610202575f80fd5b366101c357005b5f80fd5b3480156101d2575f80fd5b506101db61052f565b6040519081526020015b60405180910390f35b3480156101f9575f80fd5b506101db61053f565b34801561020d575f80fd5b5061021661054f565b6040516101e59190611afb565b34801561022e575f80fd5b506101db606481565b348015610242575f80fd5b506101db6105db565b348015610256575f80fd5b5061026a610265366004611c26565b6105fe565b6040516101e59190611cda565b348015610282575f80fd5b5061028b610676565b6040516101e593929190611d1a565b3480156102a5575f80fd5b506101db6102b4366004611d3e565b61069d565b3480156102c4575f80fd5b506102ec7f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd881565b6040516001600160a01b0390911681526020016101e5565b34801561030f575f80fd5b506004546102ec906001600160a01b031681565b34801561032e575f80fd5b506101db61099a565b348015610342575f80fd5b505f546102ec906001600160a01b031681565b348015610360575f80fd5b506101db610bf6565b348015610374575f80fd5b506002546102ec906001600160a01b031681565b348015610393575f80fd5b5061039c610c60565b604080519283526020830191909152016101e5565b3480156103bc575f80fd5b506103c5610c73565b6040516101e5929190611d55565b3480156103de575f80fd5b506103f26103ed366004611d82565b610d5c565b005b3480156103ff575f80fd5b5061028b61040e366004611c26565b610e8e565b34801561041e575f80fd5b506103f261042d366004611df6565b610e9b565b34801561043d575f80fd5b50610446610f50565b6040516101e59190611e11565b34801561045e575f80fd5b506006546102ec906001600160a01b031681565b34801561047d575f80fd5b506101db610f5c565b348015610491575f80fd5b506101db610f6c565b6103f2610f87565b3480156104ad575f80fd5b506005546102ec906001600160a01b031681565b3480156104cc575f80fd5b506101db683635c9adc5dea0000081565b3480156104e8575f80fd5b506003546102ec906001600160a01b031681565b348015610507575f80fd5b506103f2611084565b34801561051b575f80fd5b506101db61052a366004611d3e565b611146565b5f610538610676565b9392505050565b5f61054a60076111a7565b905090565b6001805461055c90611e23565b80601f016020809104026020016040519081016040528092919081815260200182805461058890611e23565b80156105d35780601f106105aa576101008083540402835291602001916105d3565b820191905f5260205f20905b8154815290600101906020018083116105b657829003601f168201915b505050505081565b5f805f6105e6610676565b925092505080826105f79190611e6f565b9250505090565b600654604051635c625c2d60e11b81526060916001600160a01b03169063b8c4b85a9061062f908590600401611e11565b5f60405180830381865afa158015610649573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106709190810190611e91565b92915050565b60605f805f61068560076111b0565b9050610690816111bc565b9196909550909350915050565b5f7f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd86001600160a01b031633146106e757604051631db8f31760e31b815260040160405180910390fd5b815f03610707576040516348d0b82d60e01b815260040160405180910390fd5b6003546040516370a0823160e01b815230600482015283916001600160a01b0316906370a0823190602401602060405180830381865afa15801561074d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107719190611f7e565b10156107905760405163171a6e5960e11b815260040160405180910390fd5b60648210156107a057505f919050565b6003546006546107bd916001600160a01b03908116911684611352565b815f683635c9adc5dea000006107d4600184611f95565b6107de9190611fa8565b6107e9906001611e6f565b90505f8167ffffffffffffffff81111561080557610805611b2d565b60405190808252806020026020018201604052801561082e578160200160208202803683370190505b5090505f5b83156108a157683635c9adc5dea00000841161084f578361085a565b683635c9adc5dea000005b82828151811061086c5761086c611fc7565b60200260200101818152505081818151811061088a5761088a611fc7565b602090810291909101015190930392600101610833565b600654604051636b34082160e11b81525f916001600160a01b03169063d6681042906108d39086903090600401611fdb565b5f604051808303815f875af11580156108ee573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109159190810190612004565b80519091505f5b8181101561095a5761095183828151811061093957610939611fc7565b6020026020010151600761145290919063ffffffff16565b5060010161091c565b50879650471561098e5761098e7f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd84761145d565b5050505050505b919050565b5f7f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd86001600160a01b031633146109e457604051631db8f31760e31b815260040160405180910390fd5b6003546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610a2a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a4e9190611f7e565b9050805f03610a5e575f91505090565b610a67816114fc565b600354604051633d7ad0b760e21b81523060048201529193505f916001600160a01b039091169063f5eb42dc90602401602060405180830381865afa158015610ab2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad69190611f7e565b90508015610bf15760035f9054906101000a90046001600160a01b03166001600160a01b0316638fcb4e5b7f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd86001600160a01b0316637b0c1f296040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b819190612090565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af1158015610bcb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bef9190611f7e565b505b505090565b6003546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610c3c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061054a9190611f7e565b5f80610c6a610676565b94909350915050565b600654604051637d031b6560e01b815230600482015260609182916001600160a01b0390911690637d031b65906024015f60405180830381865afa158015610cbd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ce49190810190612004565b600654604051635c625c2d60e11b81529193506001600160a01b03169063b8c4b85a90610d15908590600401611e11565b5f60405180830381865afa158015610d2f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d569190810190611e91565b90509091565b60065460405163e3afe0a360e01b81526001600160a01b039091169063e3afe0a390610d8e90859085906004016120ab565b5f604051808303815f87803b158015610da5575f80fd5b505af1158015610db7573d5f803e3d5ffd5b5050835191505f90505b81811015610dff57610df6848281518110610dde57610dde611fc7565b6020026020010151600761153290919063ffffffff16565b50600101610dc1565b50610e897f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd86001600160a01b0316637b0c1f296040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e5f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e839190612090565b4761145d565b505050565b60605f80610690846111bc565b5f546001600160a01b03163314610ec557604051630be1411f60e31b815260040160405180910390fd5b6001600160a01b038116610eec576040516372f5fcdf60e11b815260040160405180910390fd5b5f546040516001600160a01b038381168252909116907f2276211a3f2c7bc1943fe83cc63f8f970204ff6a4b83c690df2bc54d8f2792ad9060200160405180910390a25f80546001600160a01b0319166001600160a01b0392909216919091179055565b606061054a60076111b0565b5f610f65610676565b5092915050565b5f610f756105db565b610f7d610bf6565b61054a9190611e6f565b7f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd86001600160a01b03163314610fd057604051631db8f31760e31b815260040160405180910390fd5b345f03610ff0576040516348d0b82d60e01b815260040160405180910390fd5b60035460405163a1903eab60e01b81525f60048201819052916001600160a01b03169063a1903eab90349060240160206040518083038185885af115801561103a573d5f803e3d5ffd5b50505050506040513d601f19601f8201168201806040525081019061105f9190611f7e565b9050805f036110815760405163b6acf41560e01b815260040160405180910390fd5b50565b5f61108f60076111b0565b90505f61109b82610e8e565b505080519091505f5b81811015610dff5760065483516001600160a01b039091169063f8444436908590849081106110d5576110d5611fc7565b60200260200101516040518263ffffffff1660e01b81526004016110fb91815260200190565b5f604051808303815f87803b158015611112575f80fd5b505af1158015611124573d5f803e3d5ffd5b5050505061113d838281518110610dde57610dde611fc7565b506001016110a4565b5f7f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd86001600160a01b0316331461119057604051631db8f31760e31b815260040160405180910390fd5b815f0361119e57505f919050565b610670826114fc565b5f610670825490565b60605f6105388361153d565b60605f805f84519050805f036111d857505f915081905061134b565b8067ffffffffffffffff8111156111f1576111f1611b2d565b60405190808252806020026020018201604052801561121a578160200160208202803683370190505b50600654604051635c625c2d60e11b81529195505f916001600160a01b039091169063b8c4b85a90611250908990600401611e11565b5f60405180830381865afa15801561126a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112919190810190611e91565b80519091505f90815b81811015611344575f8482815181106112b5576112b5611fc7565b602002602001015190508060a00151156112d2575060010161129a565b80608001511561132c578982815181106112ee576112ee611fc7565b602002602001015189858060010196508151811061130e5761130e611fc7565b602090810291909101015280516113259089611e6f565b975061133b565b80516113389088611e6f565b96505b5060010161129a565b5050855250505b9193909250565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291515f928392908716916113ad91906120cf565b5f604051808303815f865af19150503d805f81146113e6576040519150601f19603f3d011682016040523d82523d5f602084013e6113eb565b606091505b509150915081801561141557508051158061141557508080602001905181019061141591906120ea565b61144b5760405162461bcd60e51b8152602060048201526002602482015261534160f01b60448201526064015b60405180910390fd5b5050505050565b5f6105388383611596565b604080515f808252602082019092526001600160a01b03841690839060405161148691906120cf565b5f6040518083038185875af1925050503d805f81146114c0576040519150601f19603f3d011682016040523d82523d5f602084013e6114c5565b606091505b5050905080610e895760405162461bcd60e51b815260206004820152600360248201526253544560e81b6044820152606401611442565b5f611506826115e2565b90506109957f0000000000000000000000005cba18d504d4158dc1a18c5dc6bb2a30b230ddd84761145d565b5f61053883836119f6565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561158a57602002820191905f5260205f20905b815481526020019060010190808311611576575b50505050509050919050565b5f8181526001830160205260408120546115db57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610670565b505f610670565b60055460405162b0e38960e81b8152600481018390525f9182916001600160a01b039091169063b0e3890090602401602060405180830381865afa15801561162c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116509190611f7e565b6002546005546004805460405163650fc20d60e11b81526fffffffffffffffffffffffffffffffff8616928101929092526001600160a01b039283166024830152821660448201529293505f9291169063ca1f841a90606401602060405180830381865afa1580156116c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116e89190611f7e565b60025460035460405163373033eb60e21b8152600481018890526001600160a01b0391821660248201529293505f9291169063dcc0cfac90604401602060405180830381865afa15801561173e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117629190611f7e565b905081158015611770575080155b1561178e576040516356d6a99560e01b815260040160405180910390fd5b5f81831161179c578161179e565b825b6002546004805460405163a74984c760e01b81526001600160a01b0391821692810192909252602482018490529293505f929091169063a74984c790604401602060405180830381865afa1580156117f8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061181c9190611f7e565b90505f8385111561194f57506005546003546001600160a01b03918216916118469116828a611352565b600554604051630ea598cb60e41b8152600481018a90526001600160a01b039091169063ea598cb0906024016020604051808303815f875af115801561188e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b29190611f7e565b6002549098506118cd9082906001600160a01b03168a611352565b6002546040516386b3abbb60e01b81526001600160a01b038381166004830152602482018b905260448201859052909116906386b3abbb906064016020604051808303815f875af1158015611924573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119489190611f7e565b965061098e565b506003546002546001600160a01b039182169161196f918391168a611352565b600254604051631818888b60e21b81526001600160a01b038381166004830152602482018b90526044820185905290911690636062222c906064016020604051808303815f875af11580156119c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ea9190611f7e565b98975050505050505050565b5f8181526001830160205260408120548015611ad0575f611a18600183611f95565b85549091505f90611a2b90600190611f95565b9050808214611a8a575f865f018281548110611a4957611a49611fc7565b905f5260205f200154905080875f018481548110611a6957611a69611fc7565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080611a9b57611a9b612103565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610670565b5f915050610670565b5f5b83811015611af3578181015183820152602001611adb565b50505f910152565b602081525f8251806020840152611b19816040850160208701611ad9565b601f01601f19169190910160400192915050565b634e487b7160e01b5f52604160045260245ffd5b60405160c0810167ffffffffffffffff81118282101715611b6457611b64611b2d565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611b9357611b93611b2d565b604052919050565b5f67ffffffffffffffff821115611bb457611bb4611b2d565b5060051b60200190565b5f82601f830112611bcd575f80fd5b81356020611be2611bdd83611b9b565b611b6a565b82815260059290921b84018101918181019086841115611c00575f80fd5b8286015b84811015611c1b5780358352918301918301611c04565b509695505050505050565b5f60208284031215611c36575f80fd5b813567ffffffffffffffff811115611c4c575f80fd5b611c5884828501611bbe565b949350505050565b5f8151808452602080850194508084015f5b83811015611ccf5781518051885283810151848901526040808201516001600160a01b0316908901526060808201519089015260808082015115159089015260a09081015115159088015260c09096019590820190600101611c72565b509495945050505050565b602081525f6105386020830184611c60565b5f8151808452602080850194508084015f5b83811015611ccf57815187529582019590820190600101611cfe565b606081525f611d2c6060830186611cec565b60208301949094525060400152919050565b5f60208284031215611d4e575f80fd5b5035919050565b604081525f611d676040830185611cec565b8281036020840152611d798185611c60565b95945050505050565b5f8060408385031215611d93575f80fd5b823567ffffffffffffffff80821115611daa575f80fd5b611db686838701611bbe565b93506020850135915080821115611dcb575f80fd5b50611dd885828601611bbe565b9150509250929050565b6001600160a01b0381168114611081575f80fd5b5f60208284031215611e06575f80fd5b813561053881611de2565b602081525f6105386020830184611cec565b600181811c90821680611e3757607f821691505b602082108103611e5557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561067057610670611e5b565b80518015158114610995575f80fd5b5f6020808385031215611ea2575f80fd5b825167ffffffffffffffff811115611eb8575f80fd5b8301601f81018513611ec8575f80fd5b8051611ed6611bdd82611b9b565b81815260c09182028301840191848201919088841115611ef4575f80fd5b938501935b83851015611f725780858a031215611f10575f8081fd5b611f18611b41565b855181528686015187820152604080870151611f3381611de2565b90820152606086810151908201526080611f4e818801611e82565b9082015260a0611f5f878201611e82565b9082015283529384019391850191611ef9565b50979650505050505050565b5f60208284031215611f8e575f80fd5b5051919050565b8181038181111561067057610670611e5b565b5f82611fc257634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b604081525f611fed6040830185611cec565b905060018060a01b03831660208301529392505050565b5f6020808385031215612015575f80fd5b825167ffffffffffffffff81111561202b575f80fd5b8301601f8101851361203b575f80fd5b8051612049611bdd82611b9b565b81815260059190911b82018301908381019087831115612067575f80fd5b928401925b828410156120855783518252928401929084019061206c565b979650505050505050565b5f602082840312156120a0575f80fd5b815161053881611de2565b604081525f6120bd6040830185611cec565b8281036020840152611d798185611cec565b5f82516120e0818460208701611ad9565b9190910192915050565b5f602082840312156120fa575f80fd5b61053882611e82565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220612627996a8c74d967f9f193429e8739aeef0243444108089ebee8508244ed6b64736f6c63430008150033
Verified Source Code Full Match
Compiler: v0.8.21+commit.d9974bed
EVM: shanghai
Optimization: Yes (200 runs)
IStETH.sol 48 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity =0.8.21;
import {IERC20} from "oz/token/ERC20/IERC20.sol";
import {IERC20Permit} from "oz/token/ERC20/extensions/IERC20Permit.sol";
/// @notice Interface defining a Lido liquid staking pool
/// @dev see also [Lido liquid staking pool core contract](https://docs.lido.fi/contracts/lido)
interface IStETH is IERC20, IERC20Permit {
/**
* @notice Send funds to the pool with optional _referral parameter
* @dev This function is alternative way to submit funds. Supports optional referral address.
* @return Amount of StETH shares generated
*/
function submit(address _referral) external payable returns (uint256);
/**
* @return the amount of shares owned by `_account`.
*/
function sharesOf(address _account) external view returns (uint256);
/**
* @notice Moves `_sharesAmount` token shares from the caller's account to the `_recipient` account.
*
* @return amount of transferred tokens.
* Emits a `TransferShares` event.
* Emits a `Transfer` event.
*
* Requirements:
*
* - `_recipient` cannot be the zero address.
* - the caller must have at least `_sharesAmount` shares.
* - the contract must not be paused.
*
* @dev The `_sharesAmount` argument is the amount of shares, not tokens.
*/
function transferShares(address _recipient, uint256 _sharesAmount) external returns (uint256);
/**
* @return the amount of shares that corresponds to `_ethAmount` protocol-controlled Ether.
*/
function getSharesByPooledEth(uint256 _pooledEthAmount) external view returns (uint256);
/**
* @return the amount of Ether that corresponds to `_sharesAmount` token shares.
*/
function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256);
}
Strategy.sol 102 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.21;
import {IStrategyManager} from "../interfaces/IStrategyManager.sol";
error Strategy__ZeroAddress();
error Strategy__NotManager();
error Strategy__NotGovernance();
abstract contract Strategy {
address payable public immutable manager;
address public governance;
string public name;
modifier onlyGovernance() {
if (governance != msg.sender) revert Strategy__NotGovernance();
_;
}
event TransferGovernance(address indexed oldOwner, address newOwner);
constructor(address payable _manager, string memory _name) {
if (_manager == address(0)) revert Strategy__NotManager();
governance = msg.sender;
manager = _manager;
name = _name;
}
/**
* @dev Throws if the caller is not the manager address.
*/
modifier onlyManager() {
if (manager != msg.sender) revert Strategy__NotManager();
_;
}
/**
* @dev Deposit function to deposit funds into the strategy.
*/
function deposit() external payable virtual onlyManager {}
/**
* @dev Withdraw function to withdraw funds from the strategy.
* @param _amount The amount of funds to withdraw.
* @return actualAmount The actual amount withdrawn.
*/
function withdraw(uint256 _amount) external virtual onlyManager returns (uint256 actualAmount) {}
/**
* @dev Instant withdraw function to immediately withdraw funds from the strategy.
* @param _amount The amount of funds to withdraw.
* @return actualAmount The actual amount withdrawn.
*/
function instantWithdraw(uint256 _amount) external virtual onlyManager returns (uint256 actualAmount) {}
/**
* @dev Clear function to clear any allocated funds or assets in the strategy.
* @return amount The amount of funds cleared.
*/
function clear() external virtual onlyManager returns (uint256 amount) {}
/**
* @dev Execute pending request function to execute any pending transactions in the strategy.
*/
function claimAllPendingAssets() external virtual;
/**
* @dev Get all value function to get the total value of assets held in the strategy.
* @return value The total value of assets held in the strategy.
*/
function getTotalValue() public virtual returns (uint256 value);
/**
* @dev Get pending value function to get the pending value of assets in the strategy.
* @return value The pending value of assets in the strategy.
*/
function getPendingValue() public virtual returns (uint256 value);
/**
* @dev Get invested value function to get the currently invested value of assets in the strategy.
* @return value The currently invested value of assets in the strategy.
*/
function getInvestedValue() public virtual returns (uint256 value);
/**
* @dev Check pending status function to check the status of pending transactions in the strategy.
* @return pending The amount of pending transactions.
* @return executable The claimable amount of transactions ready to be executed.
*/
function checkPendingStatus() external virtual returns (uint256 pending, uint256 executable);
/**
* @dev Sets the governance address.
* @param _governance The address to set as the new governance.
*/
function setGovernance(address _governance) external onlyGovernance {
if (_governance == address(0)) revert Strategy__ZeroAddress();
emit TransferGovernance(governance, _governance);
governance = _governance;
}
}
IWStETH.sol 48 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.21;
/**
* @title Wrapped stETH Interface
* @dev Interface for a contract representing wrapped staked Ether (wstETH).
*/
abstract contract IWStETH {
/**
* @dev Unwraps a specified amount of wstETH tokens into stETH tokens.
* @param _wstETHAmount The amount of wstETH tokens to unwrap.
* @return The amount of stETH tokens received.
*/
function unwrap(uint256 _wstETHAmount) external virtual returns (uint256);
/**
* @notice Exchanges stETH to wstETH
* @param _stETHAmount amount of stETH to wrap in exchange for wstETH
* @dev Requirements:
* - `_stETHAmount` must be non-zero
* - msg.sender must approve at least `_stETHAmount` stETH to this
* contract.
* - msg.sender must have at least `_stETHAmount` of stETH.
* User should first approve _stETHAmount to the WstETH contract
* @return Amount of wstETH user receives after wrap
*/
function wrap(uint256 _stETHAmount) external virtual returns (uint256);
/**
* @dev Converts a specified amount of stETH tokens into wstETH tokens.
* @param _stETHAmount The amount of stETH tokens to convert.
* @return The amount of wstETH tokens received.
*/
function getWstETHByStETH(uint256 _stETHAmount) external view virtual returns (uint256);
/**
* @dev Converts a specified amount of wstETH tokens into stETH tokens.
* @param _wstETHAmount The amount of wstETH tokens to convert.
* @return The amount of stETH tokens received.
*/
function getStETHByWstETH(uint256 _wstETHAmount) external view virtual returns (uint256);
/**
* @dev Retrieves the current exchange rate of stETH to wstETH.
* @return The current exchange rate of stETH to wstETH.
*/
function stEthPerToken() external view virtual returns (uint256);
}
ISwapManager.sol 76 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.21;
/**
* @title SwapManager Interface
* @dev Interface for a contract managing token swaps.
*/
interface ISwapManager {
/**
* @dev Swaps a specified amount of input tokens for output tokens.
* @param tokenIn The address of the input token.
* @param amountIn The amount of input tokens to swap.
* @return amountOut The amount of output tokens received.
*/
function swap(address tokenIn, uint256 amountIn) external returns (uint256 amountOut);
/**
* @dev Sets a Uniswap V3 pool address on the whitelist for a specific token.
* @param token The address of the token.
* @param pool The address of the V3 pool.
*/
function setWhitelistV3Pool(address token, address pool) external;
/**
* @dev Sets a Curve pool address on the whitelist for a specific token.
* @param token The address of the token.
* @param pool The address of the Curve pool.
*/
function setWhitelistCurvePool(address token, address pool) external;
/**
* @dev Sets the fee for a specific pool.
* @param token The address of the token.
* @param fees The fee to be set.
*/
function setPoolFee(address token, uint24 fees) external;
function transferETH() external;
/**
* @dev Estimates the output amount of a token swap using the fair quote method.
* @param tokenIn The address of the input token.
* @param amountIn The amount of input tokens.
* @return amountOut The estimated amount of output tokens.
*/
function getFairQuote(address tokenIn, uint256 amountIn) external returns (uint256 amountOut);
function swapUinv3(address tokenIn, uint256 amountIn, uint256 amountOutMinimum)
external
returns (uint256 amountOut);
function swapCurve(address tokenIn, uint256 amountIn, uint256 amountOutMinimum)
external
returns (uint256 amountOut);
function getMinimumAmount(address token, uint256 amount) external view returns (uint256);
/**
* @dev Estimates the output amount of a token swap in a Curve pool.
* @param amountIn The amount of input tokens.
* @param tokenIn The address of the input token.
* @return amountOut The estimated amount of output tokens.
*/
function estimateCurveAmountOut(uint256 amountIn, address tokenIn) external view returns (uint256 amountOut);
/**
* @dev Estimates the output amount of a token swap in a V3 pool.
* @param amountIn The amount of input tokens.
* @param tokenIn The address of the input token.
* @param tokenOut The address of the output token.
* @return amountOut The estimated amount of output tokens.
*/
function estimateV3AmountOut(uint128 amountIn, address tokenIn, address tokenOut)
external
view
returns (uint256 amountOut);
}
LidoStEthStrategy.sol 430 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.21;
import {EnumerableSet} from "oz/utils/structs/EnumerableSet.sol";
import {Strategy} from "./Strategy.sol";
import {IStETH} from "../interfaces/IStETH.sol";
import {IWStETH} from "../interfaces/IWStETH.sol";
import {ISwapManager} from "../interfaces/ISwapManager.sol";
import {IStrategyManager} from "../interfaces/IStrategyManager.sol";
import {TransferHelper} from "v3-periphery/libraries/TransferHelper.sol";
import {IWithdrawalQueueERC721} from "../interfaces/IWithdrawalQueueERC721.sol";
error Strategy__ZeroAmount();
error Strategy__LidoDeposit();
error Strategy__ZeroAddress();
error Strategy__ZeroPoolLiquidity();
error Strategy__InsufficientBalance();
/**
* @title LidoStEthStrategy
* @author Mavvverick
* @dev A strategy contract for generating eth yield by managing Lido staked ETH (stETH)
*/
contract LidoStEthStrategy is Strategy {
using EnumerableSet for EnumerableSet.UintSet;
/// @notice minimal amount of stETH that is possible to withdraw
uint256 public constant MIN_STETH_WITHDRAWAL_AMOUNT = 1_00;
/// @notice maximum amount of stETH that is possible to withdraw by a single request
/// Prevents accumulating too much funds per single request fulfillment in the future.
/// @dev To withdraw larger amounts, it's recommended to split it to several requests
uint256 public constant MAX_STETH_WITHDRAWAL_AMOUNT = 1_000 * 10 ** 18;
address public swapManager;
IStETH public STETH; //strategy token
address public WETH9; //swap token for uniV3
address public WSTETH; //swap token for uniV3
IWithdrawalQueueERC721 public stETHWithdrawalQueue;
EnumerableSet.UintSet private withdrawQueue;
/**
* @param _stETHAdress The address of the stETH contract
* @param _stETHWithdrawal The address of the stETH withdrawal contract
* @param _wstETHAdress The address of the wrapped stETH (wstETH) contract
* @param _weth9 The address of the WETH9 contract
* @param _swapManager The address of the SwapManager contract
* @param _manager The address of the strategy manager
* @param _name The name of the strategy
*/
constructor(
address _stETHAdress,
address _stETHWithdrawal,
address _wstETHAdress,
address _weth9,
address _swapManager,
address payable _manager,
string memory _name
) Strategy(_manager, _name) {
if (
_stETHAdress == address(0) || _stETHWithdrawal == address(0) || _wstETHAdress == address(0)
|| _weth9 == address(0) || _swapManager == address(0)
) revert Strategy__ZeroAddress();
STETH = IStETH(_stETHAdress);
stETHWithdrawalQueue = IWithdrawalQueueERC721(_stETHWithdrawal);
swapManager = _swapManager;
WSTETH = _wstETHAdress;
WETH9 = _weth9;
}
/**
* @dev Internal function to perform an instant withdrawal of stETH using swap pools.
* @param _amount The amount of stETH to withdraw
* @return actualAmount The actual amount of ETH withdrawn
*/
function _instantWithdraw(uint256 _amount) internal returns (uint256 actualAmount) {
// swap stEth for eth
actualAmount = _swapUsingFairQuote(_amount);
TransferHelper.safeTransferETH(manager, address(this).balance);
}
/**
* @dev Internal function to swap stETH for ETH using UniV3 or Curve.
* @param _amountIn The amount of stETH to swap
* @return actualAmount The actual amount of ETH received after swapping
*/
function _swapUsingFairQuote(uint256 _amountIn) internal returns (uint256 actualAmount) {
uint256 amountInForV3 = IWStETH(WSTETH).getWstETHByStETH(_amountIn);
uint256 v3Out = ISwapManager(swapManager).estimateV3AmountOut(uint128(amountInForV3), WSTETH, WETH9);
uint256 curveOut = ISwapManager(swapManager).estimateCurveAmountOut(_amountIn, address(STETH));
if (v3Out == 0 && curveOut == 0) revert Strategy__ZeroPoolLiquidity();
uint256 quoteAmount = v3Out > curveOut ? v3Out : curveOut;
uint256 quoteAmountMin = ISwapManager(swapManager).getMinimumAmount(WETH9, quoteAmount);
address tokenIn;
if (v3Out > curveOut) {
tokenIn = WSTETH;
// wrap stETH for uniswap pool
TransferHelper.safeApprove(address(STETH), WSTETH, _amountIn);
_amountIn = IWStETH(WSTETH).wrap(_amountIn);
TransferHelper.safeApprove(tokenIn, swapManager, _amountIn);
actualAmount = ISwapManager(swapManager).swapUinv3(tokenIn, _amountIn, quoteAmountMin);
} else {
tokenIn = address(STETH);
TransferHelper.safeApprove(tokenIn, swapManager, _amountIn);
actualAmount = ISwapManager(swapManager).swapCurve(tokenIn, _amountIn, quoteAmountMin);
}
}
function _checkPendingAssets(uint256[] memory requestIds)
internal
view
returns (uint256[] memory ids, uint256 totalClaimable, uint256 totalPending)
{
uint256 requestLen = requestIds.length;
if (requestLen == 0) return (ids, 0, 0);
ids = new uint256[](requestLen);
IWithdrawalQueueERC721.WithdrawalRequestStatus[] memory statuses =
stETHWithdrawalQueue.getWithdrawalStatus(requestIds);
uint256 index = 0;
uint256 len = statuses.length;
for (uint256 i = 0; i < len;) {
IWithdrawalQueueERC721.WithdrawalRequestStatus memory status = statuses[i];
if (status.isClaimed) {
unchecked {
i++;
}
continue;
}
if (status.isFinalized) {
unchecked {
ids[index++] = requestIds[i];
}
totalClaimable += status.amountOfStETH;
} else {
totalPending += status.amountOfStETH;
}
unchecked {
i++;
}
}
assembly {
mstore(ids, index)
}
}
/**
* @notice Deposit ETH into the Lido stETH contract.
* @dev Only the strategy manager can call this function.
*/
function deposit() external payable override onlyManager {
if (msg.value == 0) revert Strategy__ZeroAmount();
uint256 shares = STETH.submit{value: msg.value}(address(0));
if (shares == 0) revert Strategy__LidoDeposit();
}
/**
* @notice Initiate a withdrawal of a specific amount of stETH.
* @dev Only the strategy manager can call this function.
* @param _ethAmount The amount of stETH to withdraw.
* @return actualAmount The actual amount of stETH withdrawn.
*/
function withdraw(uint256 _ethAmount) external override onlyManager returns (uint256 actualAmount) {
if (_ethAmount == 0) revert Strategy__ZeroAmount();
if (STETH.balanceOf(address(this)) < _ethAmount) revert Strategy__InsufficientBalance();
// Withdrawing as little as 100 wei from the underlying strategy is not economically viable.
if (_ethAmount < MIN_STETH_WITHDRAWAL_AMOUNT) return 0;
//approve steth for WithdrawalQueueERC721
TransferHelper.safeApprove(address(STETH), address(stETHWithdrawalQueue), _ethAmount);
uint256 remainingBalance = _ethAmount;
uint256 batchLen = ((_ethAmount - 1) / MAX_STETH_WITHDRAWAL_AMOUNT) + 1;
uint256[] memory requestedAmounts = new uint256[](batchLen);
uint256 index;
while (remainingBalance != 0) {
requestedAmounts[index] =
remainingBalance > MAX_STETH_WITHDRAWAL_AMOUNT ? MAX_STETH_WITHDRAWAL_AMOUNT : remainingBalance;
unchecked {
remainingBalance -= requestedAmounts[index];
index++;
}
}
//raise a withdraw request to WithdrawalQueueERC721
uint256[] memory ids = stETHWithdrawalQueue.requestWithdrawals(requestedAmounts, address(this));
uint256 idsLen = ids.length;
// push the withdraw request id
for (uint256 i = 0; i < idsLen;) {
withdrawQueue.add(ids[i]);
unchecked {
i++;
}
}
actualAmount = _ethAmount;
if (address(this).balance > 0) {
TransferHelper.safeTransferETH(manager, address(this).balance);
}
}
/**
* @notice Claim all pending withdrawal assets from the stETH withdrawal queue.
* @dev This function claims all pending withdrawal assets and transfers them to the assets vault.
* Check claimable pending assets before calling this function.
* The queue will always stay within bounds since withdrawal is requested once per rebase cycle,
* which is 365 requests in a year for a 1-day epoch cycle or 52 requests in a year for a 7-day epoch cycle
* If the queue expands to a level where withdrawQueue consumes excessive gas, use claimAllPendingAssetsByIds instead.
*/
function claimAllPendingAssets() external override {
uint256[] memory withdrawIds = withdrawQueue.values();
(uint256[] memory ids,,) = checkPendingAssets(withdrawIds);
uint256 len = ids.length;
for (uint256 i = 0; i < len;) {
stETHWithdrawalQueue.claimWithdrawal(ids[i]);
// remove claimed request Ids
withdrawQueue.remove(ids[i]);
unchecked {
i++;
}
}
TransferHelper.safeTransferETH(IStrategyManager(manager).assetsVault(), address(this).balance);
}
/**
* @notice Redeems eth amount and deposit redeemed amount in the bridge
* NB! Array of request ids should be sorted
* @param claimableRequestIds An array of withdrawal request IDs that are claimable
* @param hints Array of hints used to find required checkpoint for the request
* Reverts if requestIds and hints arrays length differs
* Reverts if any requestId or hint in arguments are not valid
* Reverts if any request is not finalized or already claimed
*/
function claimAllPendingAssetsByIds(uint256[] memory claimableRequestIds, uint256[] memory hints) external {
// Claim withdrawal amount
// Reverts if any request is not finalized or already claimed
stETHWithdrawalQueue.claimWithdrawals(claimableRequestIds, hints);
// remove claimed request Ids
uint256 requestsLen = claimableRequestIds.length;
for (uint256 i = 0; i < requestsLen;) {
withdrawQueue.remove(claimableRequestIds[i]);
unchecked {
i++;
}
}
// Transfer the claimed asset to the assets vault
TransferHelper.safeTransferETH(IStrategyManager(manager).assetsVault(), address(this).balance);
}
/**
* @notice Initiate an instant withdrawal of stETH using swap pools
* @dev Only the strategy manager can call this function.
* @param _amount The amount of stETH to withdraw.
* @return actualAmount The actual amount of stETH withdrawn.
*/
function instantWithdraw(uint256 _amount) external override onlyManager returns (uint256 actualAmount) {
if (_amount == 0) return 0;
actualAmount = _instantWithdraw(_amount);
}
/**
* @notice Clear the strategy by withdrawing all stETH to the assets vault
* @dev This function withdraws all stETH from the strategy and transfers them to the strategy manager's assets vault.
* @return amount The amount of stETH withdrawn.
*/
function clear() external override onlyManager returns (uint256 amount) {
uint256 balance = STETH.balanceOf(address(this));
// if stEth shares is zero return actualAmount = 0
if (balance == 0) return 0;
amount = _instantWithdraw(balance);
// Transfer left over dust shares to the asset vault
uint256 share = STETH.sharesOf(address(this));
if (share > 0) {
STETH.transferShares(IStrategyManager(manager).assetsVault(), share);
}
}
/**
* @notice Check the pending withdrawal assets from the stETH withdrawal queue.
* @dev This function retrieves the pending withdrawal assets and returns their IDs, total claimable amount, and total pending amount.
* @return ids An array of withdrawal request IDs.
* @return totalClaimable The total amount of claimable stETH.
* @return totalPending The total amount of pending stETH.
*/
function checkPendingAssets()
public
view
returns (uint256[] memory ids, uint256 totalClaimable, uint256 totalPending)
{
uint256[] memory requestIds = withdrawQueue.values();
(ids, totalClaimable, totalPending) = _checkPendingAssets(requestIds);
}
/**
* @notice Check the pending withdrawal assets from the stETH withdrawal queue.
* @dev This function retrieves the pending withdrawal assets and returns their IDs, total claimable amount, and total pending amount.
* @param requestIds An array of withdrawal request IDs
* @return ids An array of withdrawal request IDs.
* @return totalClaimable The total amount of claimable stETH.
* @return totalPending The total amount of pending stETH.
*/
function checkPendingAssets(uint256[] memory requestIds)
public
view
returns (uint256[] memory ids, uint256 totalClaimable, uint256 totalPending)
{
(ids, totalClaimable, totalPending) = _checkPendingAssets(requestIds);
}
/**
* @notice Get the pending and executable assets amount
* @dev This function retrieves the pending and executable assets from the stETH withdrawal queue.
* @return pending The total amount of pending stETH.
* @return executable The total amount of claimable stETH.
*/
function checkPendingStatus() external view override returns (uint256 pending, uint256 executable) {
(, executable, pending) = checkPendingAssets();
}
/**
* @notice Retrieves the withdrawal request ids
* @return requestIds An array of withdrawal request IDs
*/
function getRequestIds() public view returns (uint256[] memory requestIds) {
return withdrawQueue.values();
}
/**
* @notice Retrieves the withdrawal request ids
* @return requestIdsLength An array size of withdrawal request IDs
*/
function getRequestIdsLen() public view returns (uint256 requestIdsLength) {
return withdrawQueue.length();
}
/**
* @notice Retrieves the withdrawal status of stETH requests
* @return requestIds An array of withdrawal request IDs
* @return statuses An array of withdrawal request statuses
*/
function getStETHWithdrawalStatus()
public
view
returns (uint256[] memory requestIds, IWithdrawalQueueERC721.WithdrawalRequestStatus[] memory statuses)
{
requestIds = stETHWithdrawalQueue.getWithdrawalRequests(address(this));
statuses = stETHWithdrawalQueue.getWithdrawalStatus(requestIds);
}
/**
* @notice Retrieves the withdrawal status of stETH requests
* NB! Array of request ids should be sorted
* @param requestIds An array of stETH withdrawal request IDs for claim
* @return statuses An array of withdrawal request statuses
*/
function getStETHWithdrawalStatusForIds(uint256[] memory requestIds)
public
view
returns (IWithdrawalQueueERC721.WithdrawalRequestStatus[] memory statuses)
{
statuses = stETHWithdrawalQueue.getWithdrawalStatus(requestIds);
}
/**
* @notice Get the total value of assets managed by the strategy.
* @dev This function retrieves the total value of assets managed by the strategy, including invested, claimable, and pending values.
* @return value The total value of assets managed by the strategy.
*/
function getTotalValue() public view override returns (uint256 value) {
value = getInvestedValue() + getClaimableAndPendingValue();
}
/**
* @notice Get the invested value of assets managed by the strategy.
* @dev This function retrieves the invested value of assets managed by the strategy.
* @return value The invested value of assets managed by the strategy.
*/
function getInvestedValue() public view override returns (uint256 value) {
value = STETH.balanceOf(address(this));
}
/**
* @notice Get the pending value of assets managed by the strategy.
* @dev This function retrieves the pending value of assets managed by the strategy.
* @return value The pending value of assets managed by the strategy.
*/
function getPendingValue() public view override returns (uint256 value) {
(,, value) = checkPendingAssets();
}
/**
* @notice Get the claimable value of assets managed by the strategy.
* @dev This function retrieves the claimable value of assets managed by the strategy.
* @return value The claimable value of assets managed by the strategy.
*/
function getClaimableValue() public view returns (uint256 value) {
(, value,) = checkPendingAssets();
}
/**
* @notice Get the total claimable and pending value of assets managed by the strategy.
* @dev This function retrieves the total claimable and pending value of assets managed by the strategy.
* @return value The total claimable and pending value of assets managed by the strategy.
*/
function getClaimableAndPendingValue() public view returns (uint256 value) {
(, uint256 claimableValue, uint256 pendingValue) = checkPendingAssets();
value = claimableValue + pendingValue;
}
receive() external payable {}
}
IStrategyManager.sol 82 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.21;
/**
* @title StrategyManager Interface
* @dev Interface for a contract managing multiple eth investment strategies.
*/
interface IStrategyManager {
/**
* @dev Sets a new vault address.
* @param _vault The address of the new vault.
*/
function setNewVault(address _vault) external;
/**
* @dev Adds a new strategy to be managed.
* @param _strategy The address of the strategy to add.
*/
function addStrategy(address _strategy) external;
/**
* @dev Destroys a strategy, removing it from management.
* @param _strategy The address of the strategy to destroy.
*/
function destroyStrategy(address _strategy) external;
/**
* @dev Clears a strategy, potentially withdrawing its funds and resetting parameters.
* @param _strategy The address of the strategy to clear.
*/
function clearStrategy(address _strategy) external;
/**
* @dev Rebalances the strategies based on incoming and outgoing amounts.
* @param amountIn The amount of funds to be rebalanced into the strategies.
* @param amountOut The amount of funds to be rebalanced out of the strategies.
*/
function rebaseStrategies(uint256 amountIn, uint256 amountOut) external;
/**
* @dev Rebalances the strategies without incoming and outgoing amounts.
*/
function onlyRebaseStrategies() external;
/**
* @dev Forces a withdrawal of a specified amount of ETH from the strategies.
* @param ethAmount The amount of ETH to withdraw.
* @return actualAmount The actual amount of ETH withdrawn.
*/
function forceWithdraw(uint256 ethAmount) external returns (uint256 actualAmount);
/**
* @dev Sets the strategies and their corresponding ratios.
* @param _strategies The addresses of the strategies to set.
* @param _ratios The corresponding ratios for each strategy.
*/
function setStrategies(address[] memory _strategies, uint256[] memory _ratios) external;
/**
* @dev Retrieves the address of the assets vault managed by the strategy manager.
* @return vault The address of the assets vault.
*/
function assetsVault() external view returns (address vault);
/**
* @dev Retrieves the total value managed by all strategies.
* @return amount The total value managed by all strategies.
*/
function getAllStrategiesValue() external view returns (uint256 amount);
/**
* @dev Retrieves the total valid value managed by all strategies.
* @return amount The total valid value managed by all strategies.
*/
function getTotalInvestedValue() external view returns (uint256 amount);
/**
* @dev Retrieves the total pending value managed by all strategies.
* @return amount The total pending value managed by all strategies.
*/
function getAllStrategyPendingValue() external view returns (uint256 amount);
}
IWithdrawalQueueERC721.sol 111 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.21;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IWithdrawalQueueERC721 is IERC721 {
/// @notice output format struct for `_getWithdrawalStatus()` method
struct WithdrawalRequestStatus {
/// @notice stETH token amount that was locked on withdrawal queue for this request
uint256 amountOfStETH;
/// @notice amount of stETH shares locked on withdrawal queue for this request
uint256 amountOfShares;
/// @notice address that can claim or transfer this request
address owner;
/// @notice timestamp of when the request was created, in seconds
uint256 timestamp;
/// @notice true, if request is finalized
bool isFinalized;
/// @notice true, if request is claimed. Request is claimable if (isFinalized && !isClaimed)
bool isClaimed;
}
/// @dev See {IERC721-balanceOf}.
function balanceOf(address _owner) external view returns (uint256);
/// @notice Returns all withdrawal requests that belongs to the `_owner` address
///
/// WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
/// to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
/// this function has an unbounded cost, and using it as part of a state-changing function may render the function
/// uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
function getWithdrawalRequests(address _owner) external view returns (uint256[] memory requestsIds);
/// @notice Returns status for requests with provided ids
/// @param _requestIds array of withdrawal request ids
function getWithdrawalStatus(uint256[] calldata _requestIds)
external
view
returns (WithdrawalRequestStatus[] memory statuses);
/// @notice length of the checkpoint array. Last possible value for the hint.
/// NB! checkpoints are indexed from 1, so it returns 0 if there is no checkpoints
function getLastCheckpointIndex() external view returns (uint256);
/// @notice Request the batch of stETH for withdrawal. Approvals for the passed amounts should be done before.
/// @param _amounts an array of stETH amount values.
/// The standalone withdrawal request will be created for each item in the passed list.
/// @param _owner address that will be able to manage the created requests.
/// If `address(0)` is passed, `msg.sender` will be used as owner.
/// @return requestIds an array of the created withdrawal request ids
function requestWithdrawals(uint256[] calldata _amounts, address _owner)
external
returns (uint256[] memory requestIds);
/// @notice Finds the list of hints for the given `_requestIds` searching among the checkpoints with indices
/// in the range `[_firstIndex, _lastIndex]`.
/// NB! Array of request ids should be sorted
/// NB! `_firstIndex` should be greater than 0, because checkpoint list is 1-based array
/// Usage: findCheckpointHints(_requestIds, 1, getLastCheckpointIndex())
/// @param _requestIds ids of the requests sorted in the ascending order to get hints for
/// @param _firstIndex left boundary of the search range. Should be greater than 0
/// @param _lastIndex right boundary of the search range. Should be less than or equal to getLastCheckpointIndex()
/// @return hintIds array of hints used to find required checkpoint for the request
function findCheckpointHints(uint256[] calldata _requestIds, uint256 _firstIndex, uint256 _lastIndex)
external
view
returns (uint256[] memory hintIds);
/// @notice Claim a batch of withdrawal requests if they are finalized sending locked ether to the owner
/// @param _requestIds array of request ids to claim
/// @param _hints checkpoint hint for each id. Can be obtained with `findCheckpointHints()`
/// @dev
/// Reverts if requestIds and hints arrays length differs
/// Reverts if any requestId or hint in arguments are not valid
/// Reverts if any request is not finalized or already claimed
/// Reverts if msg sender is not an owner of the requests
function claimWithdrawals(uint256[] calldata _requestIds, uint256[] calldata _hints) external;
/// @notice Claim one`_requestId` request once finalized sending locked ether to the owner
/// @param _requestId request id to claim
/// @dev use unbounded loop to find a hint, which can lead to OOG
/// @dev
/// Reverts if requestId or hint are not valid
/// Reverts if request is not finalized or already claimed
/// Reverts if msg sender is not an owner of request
function claimWithdrawal(uint256 _requestId) external;
/// @notice Claim a batch of withdrawal requests if they are finalized sending ether to `_recipient`
/// @param _requestIds array of request ids to claim
/// @param _hints checkpoint hint for each id. Can be obtained with `findCheckpointHints()`
/// @param _recipient address where claimed ether will be sent to
/// @dev
/// Reverts if recipient is equal to zero
/// Reverts if requestIds and hints arrays length differs
/// Reverts if any requestId or hint in arguments are not valid
/// Reverts if any request is not finalized or already claimed
/// Reverts if msg sender is not an owner of the requests
function claimWithdrawalsTo(uint256[] calldata _requestIds, uint256[] calldata _hints, address _recipient)
external;
function finaliseRequest(uint256 _requestId) external;
function finalize(uint256 _lastRequestIdToBeFinalized, uint256 _maxShareRate) external payable;
function getLastRequestId() external view returns (uint256);
function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate)
external
view
returns (uint256 ethToLock, uint256 sharesToBurn);
}
TransferHelper.sol 60 lines
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
library TransferHelper {
/// @notice Transfers tokens from the targeted address to the given destination
/// @notice Errors with 'STF' if transfer fails
/// @param token The contract address of the token to be transferred
/// @param from The originating address from which the tokens will be transferred
/// @param to The destination address of the transfer
/// @param value The amount to be transferred
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
}
/// @notice Transfers tokens from msg.sender to a recipient
/// @dev Errors with ST if transfer fails
/// @param token The contract address of the token which will be transferred
/// @param to The recipient of the transfer
/// @param value The value of the transfer
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
}
/// @notice Approves the stipulated contract to spend the given allowance in the given token
/// @dev Errors with 'SA' if transfer fails
/// @param token The contract address of the token to be approved
/// @param to The target of the approval
/// @param value The amount of the given token the target will be allowed to spend
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
}
/// @notice Transfers ETH to the recipient address
/// @dev Fails with `STE`
/// @param to The destination of the transfer
/// @param value The value to be transferred
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'STE');
}
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev 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.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens 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.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
IERC721.sol 135 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
EnumerableSet.sol 378 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.20;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 value => uint256) _positions;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
IERC20Permit.sol 90 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
Read Contract
MAX_STETH_WITHDRAWAL_AMOUNT 0xdb2296cd → uint256
MIN_STETH_WITHDRAWAL_AMOUNT 0x0d25a957 → uint256
STETH 0xe00bfe50 → address
WETH9 0x4aa4a4fc → address
WSTETH 0xd9fb643a → address
checkPendingAssets 0x1c2ca2fd → uint256[], uint256, uint256
checkPendingAssets 0x9e354677 → uint256[], uint256, uint256
checkPendingStatus 0x75421af3 → uint256, uint256
getClaimableAndPendingValue 0x162275f4 → uint256
getClaimableValue 0xc00f60c4 → uint256
getInvestedValue 0x6c23ab4c → uint256
getPendingValue 0x001a5597 → uint256
getRequestIds 0xac33a273 → uint256[]
getRequestIdsLen 0x03f112e5 → uint256
getStETHWithdrawalStatus 0x7ca9c0f9 → uint256[], tuple[]
getStETHWithdrawalStatusForIds 0x1b63a9ec → tuple[]
getTotalValue 0xcaa648b4 → uint256
governance 0x5aa6e675 → address
manager 0x481c6a75 → address
name 0x06fdde03 → string
stETHWithdrawalQueue 0xb9a5e719 → address
swapManager 0x709d039d → address
Write Contract 7 functions
These functions modify contract state and require a wallet transaction to execute.
claimAllPendingAssets 0xeea94dab
No parameters
claimAllPendingAssetsByIds 0x83b39e23
uint256[] claimableRequestIds
uint256[] hints
clear 0x52efea6e
No parameters
returns: uint256
deposit 0xd0e30db0
No parameters
instantWithdraw 0xfd92bff2
uint256 _amount
returns: uint256
setGovernance 0xab033ea9
address _governance
withdraw 0x2e1a7d4d
uint256 _ethAmount
returns: uint256
Token Balances (1)
View Transfers →Recent Transactions
No transactions found for this address