-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SI][Vaults] feat: Dashboard UX updates #915
Changes from 22 commits
b6156ad
a11d6b6
29ef4ad
b5c839f
4b16505
41f6125
ae59476
de3d3b9
3261a8c
c228afd
c6cc70f
739a60d
839b726
99f7d9a
186e266
0aea721
c4e7ceb
62710b0
95b11fb
b5ce3a4
fe87ca3
50259ec
fac1f9d
710ccac
77d8739
0903095
5300444
f24c48e
90f64d4
5a907fc
b529f7b
5215e35
f78235c
bea9a49
616a0f8
2b871fb
c9c7f74
e470a89
4ff312b
34d4519
b7e5536
0c2c170
067f38b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
folkyatina marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please update following comment:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. votingCommittee -> multiConfirmationRoles There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reserveRatio() -> reserveRatioBP() or at least comment that this is the BP convention There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's document whether already minted are included or not
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -1,23 +1,24 @@ | ||||||||||
// SPDX-FileCopyrightText: 2025 Lido <info@lido.fi> | ||||||||||
// SPDX-License-Identifier: GPL-3.0 | ||||||||||
// SPDX-FileCopyrightText: 2024 Lido <info@lido.fi> | ||||||||||
|
||||||||||
// See contracts/COMPILERS.md | ||||||||||
pragma solidity 0.8.25; | ||||||||||
|
||||||||||
import {AccessControlEnumerable} from "@openzeppelin/contracts-v5.0.2/access/extensions/AccessControlEnumerable.sol"; | ||||||||||
import {OwnableUpgradeable} from "contracts/openzeppelin/5.0.2/upgradeable/access/OwnableUpgradeable.sol"; | ||||||||||
import {IERC20} from "@openzeppelin/contracts-v5.0.2/token/ERC20/IERC20.sol"; | ||||||||||
import {IERC20Permit} from "@openzeppelin/contracts-v5.0.2/token/ERC20/extensions/IERC20Permit.sol"; | ||||||||||
|
||||||||||
import {Math256} from "contracts/common/lib/Math256.sol"; | ||||||||||
|
||||||||||
import {VaultHub} from "./VaultHub.sol"; | ||||||||||
|
||||||||||
import {IStakingVault} from "./interfaces/IStakingVault.sol"; | ||||||||||
import {ILido as IStETH} from "../interfaces/ILido.sol"; | ||||||||||
import {IERC20} from "@openzeppelin/contracts-v5.0.2/token/ERC20/IERC20.sol"; | ||||||||||
import {IERC721} from "@openzeppelin/contracts-v5.0.2/token/ERC721/IERC721.sol"; | ||||||||||
import {IERC20Permit} from "@openzeppelin/contracts-v5.0.2/token/ERC20/extensions/IERC20Permit.sol"; | ||||||||||
import {ILido as IStETH} from "contracts/0.8.25/interfaces/ILido.sol"; | ||||||||||
import {ILidoLocator} from "contracts/common/interfaces/ILidoLocator.sol"; | ||||||||||
import {IStakingVault} from "contracts/0.8.25/vaults/interfaces/IStakingVault.sol"; | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
|
||||||||||
interface IWeth is IERC20 { | ||||||||||
function withdraw(uint) external; | ||||||||||
interface IWETH9 is IERC20 { | ||||||||||
function withdraw(uint256) external; | ||||||||||
|
||||||||||
function deposit() external payable; | ||||||||||
} | ||||||||||
|
@@ -54,7 +55,10 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
IWstETH public immutable WSTETH; | ||||||||||
|
||||||||||
/// @notice The wrapped ether token contract | ||||||||||
IWeth public immutable WETH; | ||||||||||
IWETH9 public immutable WETH; | ||||||||||
|
||||||||||
/// @notice ETH address convention per EIP-7528 | ||||||||||
address public constant ETH = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
|
||||||||||
/// @notice The underlying `StakingVault` contract | ||||||||||
IStakingVault public stakingVault; | ||||||||||
|
@@ -71,20 +75,18 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @notice Constructor sets the stETH token address and the implementation contract address. | ||||||||||
* @param _stETH Address of the stETH token contract. | ||||||||||
* @notice Constructor sets the stETH, WETH, and WSTETH token addresses. | ||||||||||
* @param _weth Address of the weth token contract. | ||||||||||
* @param _wstETH Address of the wstETH token contract. | ||||||||||
* @param _lidoLocator Address of the Lido locator contract. | ||||||||||
*/ | ||||||||||
constructor(address _stETH, address _weth, address _wstETH) { | ||||||||||
if (_stETH == address(0)) revert ZeroArgument("_stETH"); | ||||||||||
constructor(address _weth, address _lidoLocator) { | ||||||||||
if (_weth == address(0)) revert ZeroArgument("_WETH"); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
if (_wstETH == address(0)) revert ZeroArgument("_wstETH"); | ||||||||||
if (_lidoLocator == address(0)) revert ZeroArgument("_lidoLocator"); | ||||||||||
|
||||||||||
_SELF = address(this); | ||||||||||
STETH = IStETH(_stETH); | ||||||||||
WETH = IWeth(_weth); | ||||||||||
WSTETH = IWstETH(_wstETH); | ||||||||||
WETH = IWETH9(_weth); | ||||||||||
STETH = IStETH(ILidoLocator(_lidoLocator).lido()); | ||||||||||
WSTETH = IWstETH(ILidoLocator(_lidoLocator).wstETH()); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
|
@@ -109,6 +111,12 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
vaultHub = VaultHub(stakingVault.vaultHub()); | ||||||||||
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's add an admin argument to avoid using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe a bit later will be done by @failingtwice |
||||||||||
|
||||||||||
// reduces gas cost for `burnWsteth` | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
// dashboard will hold STETH during this tx | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
STETH.approve(address(WSTETH), type(uint256).max); | ||||||||||
// allows to uncondinitialy use transferFrom in _burn | ||||||||||
STETH.approve(address(this), type(uint256).max); | ||||||||||
|
||||||||||
emit Initialized(); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we emit args of the init? |
||||||||||
} | ||||||||||
|
||||||||||
|
@@ -180,11 +188,11 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
|
||||||||||
/** | ||||||||||
* @notice Returns the maximum number of shares that can be minted with deposited ether. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
* @param _ether the amount of ether to be funded, can be zero | ||||||||||
* @param _etherToFund the amount of ether to be funded, can be zero | ||||||||||
* @return the maximum number of shares that can be minted by ether | ||||||||||
*/ | ||||||||||
function getMintableShares(uint256 _ether) external view returns (uint256) { | ||||||||||
uint256 _totalShares = _totalMintableShares(stakingVault.valuation() + _ether); | ||||||||||
function projectedMintableShares(uint256 _etherToFund) external view returns (uint256) { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
not a strong opinion though, just to disambiguate with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
uint256 _totalShares = _totalMintableShares(stakingVault.valuation() + _etherToFund); | ||||||||||
uint256 _sharesMinted = vaultSocket().sharesMinted; | ||||||||||
|
||||||||||
if (_totalShares < _sharesMinted) return 0; | ||||||||||
|
@@ -199,14 +207,11 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
return Math256.min(address(stakingVault).balance, stakingVault.unlocked()); | ||||||||||
} | ||||||||||
|
||||||||||
// TODO: add preview view methods for minting and burning | ||||||||||
|
||||||||||
// ==================== Vault Management Functions ==================== | ||||||||||
|
||||||||||
/** | ||||||||||
* @dev Receive function to accept ether | ||||||||||
*/ | ||||||||||
// TODO: Consider the amount of ether on balance of the contract | ||||||||||
receive() external payable { | ||||||||||
if (msg.value == 0) revert ZeroArgument("msg.value"); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
why do we need this though? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
} | ||||||||||
|
@@ -230,7 +235,7 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
* @notice Funds the staking vault with ether | ||||||||||
*/ | ||||||||||
function fund() external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) { | ||||||||||
_fund(); | ||||||||||
_fund(msg.value); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
|
@@ -243,8 +248,7 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
WETH.transferFrom(msg.sender, address(this), _wethAmount); | ||||||||||
WETH.withdraw(_wethAmount); | ||||||||||
|
||||||||||
// TODO: find way to use _fund() instead of stakingVault directly | ||||||||||
stakingVault.fund{value: _wethAmount}(); | ||||||||||
_fund(_wethAmount); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
|
@@ -280,7 +284,7 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
* @param _recipient Address of the recipient | ||||||||||
* @param _amountOfShares Amount of shares to mint | ||||||||||
*/ | ||||||||||
function mint( | ||||||||||
function mintShares( | ||||||||||
folkyatina marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
address _recipient, | ||||||||||
uint256 _amountOfShares | ||||||||||
) external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) fundAndProceed { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we still need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no, fixed |
||||||||||
|
@@ -290,41 +294,38 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
/** | ||||||||||
* @notice Mints wstETH tokens backed by the vault to a recipient. Approvals for the passed amounts should be done before. | ||||||||||
Jeday marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
* @param _recipient Address of the recipient | ||||||||||
* @param _tokens Amount of tokens to mint | ||||||||||
* @param _amountOfWstETH Amount of tokens to mint | ||||||||||
*/ | ||||||||||
function mintWstETH( | ||||||||||
address _recipient, | ||||||||||
uint256 _tokens | ||||||||||
uint256 _amountOfWstETH | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. amountX vs Xamount is a bit incosistent There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
) external payable virtual onlyRole(DEFAULT_ADMIN_ROLE) fundAndProceed { | ||||||||||
_mint(address(this), _tokens); | ||||||||||
_mint(address(this), _amountOfWstETH); | ||||||||||
|
||||||||||
uint256 stETHAmount = STETH.getPooledEthByShares(_amountOfWstETH); | ||||||||||
Jeday marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
||||||||||
STETH.approve(address(WSTETH), _tokens); | ||||||||||
uint256 wstETHAmount = WSTETH.wrap(_tokens); | ||||||||||
uint256 wstETHAmount = WSTETH.wrap(stETHAmount); | ||||||||||
WSTETH.transfer(_recipient, wstETHAmount); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @notice Burns stETH shares from the sender backed by the vault | ||||||||||
* @param _amountOfShares Amount of shares to burn | ||||||||||
*/ | ||||||||||
function burn(uint256 _amountOfShares) external virtual onlyRole(DEFAULT_ADMIN_ROLE) { | ||||||||||
_burn(_amountOfShares); | ||||||||||
function burnShares(uint256 _amountOfShares) external virtual onlyRole(DEFAULT_ADMIN_ROLE) { | ||||||||||
_burn(msg.sender, _amountOfShares); | ||||||||||
Jeday marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @notice Burns wstETH tokens from the sender backed by the vault. Approvals for the passed amounts should be done before. | ||||||||||
* @param _tokens Amount of wstETH tokens to burn | ||||||||||
* @param _amountOfWstETH Amount of wstETH tokens to burn | ||||||||||
* @dev The _amountOfWstETH = _amountOfShares by design | ||||||||||
*/ | ||||||||||
function burnWstETH(uint256 _tokens) external virtual onlyRole(DEFAULT_ADMIN_ROLE) { | ||||||||||
WSTETH.transferFrom(msg.sender, address(this), _tokens); | ||||||||||
function burnWstETH(uint256 _amountOfWstETH) external virtual onlyRole(DEFAULT_ADMIN_ROLE) { | ||||||||||
folkyatina marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
WSTETH.transferFrom(msg.sender, address(this), _amountOfWstETH); | ||||||||||
WSTETH.unwrap(_amountOfWstETH); | ||||||||||
|
||||||||||
uint256 stETHAmount = WSTETH.unwrap(_tokens); | ||||||||||
|
||||||||||
STETH.transfer(address(vaultHub), stETHAmount); | ||||||||||
|
||||||||||
uint256 sharesAmount = STETH.getSharesByPooledEth(stETHAmount); | ||||||||||
|
||||||||||
vaultHub.burnSharesBackedByVault(address(stakingVault), sharesAmount); | ||||||||||
_burn(address(this), _amountOfWstETH); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
|
@@ -362,43 +363,40 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
|
||||||||||
/** | ||||||||||
* @notice Burns stETH tokens from the sender backed by the vault using EIP-2612 Permit. | ||||||||||
* @param _tokens Amount of stETH tokens to burn | ||||||||||
* @param _amountOfShares Amount of shares to burn | ||||||||||
* @param _permit data required for the stETH.permit() method to set the allowance | ||||||||||
*/ | ||||||||||
function burnWithPermit( | ||||||||||
uint256 _tokens, | ||||||||||
function burnSharesWithPermit( | ||||||||||
folkyatina marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
uint256 _amountOfShares, | ||||||||||
PermitInput calldata _permit | ||||||||||
) | ||||||||||
external | ||||||||||
virtual | ||||||||||
onlyRole(DEFAULT_ADMIN_ROLE) | ||||||||||
trustlessPermit(address(STETH), msg.sender, address(this), _permit) | ||||||||||
Jeday marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
{ | ||||||||||
_burn(_tokens); | ||||||||||
_burn(msg.sender, _amountOfShares); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @notice Burns wstETH tokens from the sender backed by the vault using EIP-2612 Permit. | ||||||||||
* @param _tokens Amount of wstETH tokens to burn | ||||||||||
* @param _amountOfWstETH Amount of wstETH tokens to burn | ||||||||||
* @param _permit data required for the wstETH.permit() method to set the allowance | ||||||||||
*/ | ||||||||||
function burnWstETHWithPermit( | ||||||||||
uint256 _tokens, | ||||||||||
uint256 _amountOfWstETH, | ||||||||||
PermitInput calldata _permit | ||||||||||
) | ||||||||||
external | ||||||||||
virtual | ||||||||||
onlyRole(DEFAULT_ADMIN_ROLE) | ||||||||||
trustlessPermit(address(WSTETH), msg.sender, address(this), _permit) | ||||||||||
{ | ||||||||||
WSTETH.transferFrom(msg.sender, address(this), _tokens); | ||||||||||
uint256 stETHAmount = WSTETH.unwrap(_tokens); | ||||||||||
|
||||||||||
STETH.transfer(address(vaultHub), stETHAmount); | ||||||||||
|
||||||||||
WSTETH.transferFrom(msg.sender, address(this), _amountOfWstETH); | ||||||||||
uint256 stETHAmount = WSTETH.unwrap(_amountOfWstETH); | ||||||||||
uint256 sharesAmount = STETH.getSharesByPooledEth(stETHAmount); | ||||||||||
|
||||||||||
vaultHub.burnSharesBackedByVault(address(stakingVault), sharesAmount); | ||||||||||
_burn(address(this), sharesAmount); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
|
@@ -409,14 +407,49 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
_rebalanceVault(_ether); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @notice recovers ERC20 tokens or ether from the dashboard contract to sender | ||||||||||
TheDZhon marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
* @param _token Address of the token to recover or 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee for ether | ||||||||||
*/ | ||||||||||
function recoverERC20(address _token) external onlyRole(DEFAULT_ADMIN_ROLE) { | ||||||||||
uint256 _amount; | ||||||||||
if (_token == address(0)) revert ZeroArgument("_token"); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
|
||||||||||
if (_token == ETH) { | ||||||||||
_amount = address(this).balance; | ||||||||||
payable(msg.sender).transfer(_amount); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
} else { | ||||||||||
_amount = IERC20(_token).balanceOf(address(this)); | ||||||||||
bool success = IERC20(_token).transfer(msg.sender, _amount); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SafeERC20 lib There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||
if (!success) revert("ERC20: Transfer failed"); | ||||||||||
} | ||||||||||
|
||||||||||
emit ERC20Recovered(msg.sender, _token, _amount); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @notice Transfers a given token_id of an ERC721-compatible NFT (defined by the token contract address) | ||||||||||
* from the dashboard contract to sender | ||||||||||
* | ||||||||||
* @param _token an ERC721-compatible token | ||||||||||
* @param _tokenId token id to recover | ||||||||||
*/ | ||||||||||
function recoverERC721(address _token, uint256 _tokenId) external onlyRole(DEFAULT_ADMIN_ROLE) { | ||||||||||
if (_token == address(0)) revert ZeroArgument("_token"); | ||||||||||
|
||||||||||
emit ERC721Recovered(msg.sender, _token, _tokenId); | ||||||||||
|
||||||||||
IERC721(_token).transferFrom(address(this), msg.sender, _tokenId); | ||||||||||
Jeday marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
} | ||||||||||
|
||||||||||
// ==================== Internal Functions ==================== | ||||||||||
|
||||||||||
/** | ||||||||||
* @dev Modifier to fund the staking vault if msg.value > 0 | ||||||||||
*/ | ||||||||||
modifier fundAndProceed() { | ||||||||||
if (msg.value > 0) { | ||||||||||
_fund(); | ||||||||||
_fund(msg.value); | ||||||||||
} | ||||||||||
_; | ||||||||||
} | ||||||||||
|
@@ -444,8 +477,8 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
/** | ||||||||||
* @dev Funds the staking vault with the ether sent in the transaction | ||||||||||
*/ | ||||||||||
function _fund() internal { | ||||||||||
stakingVault.fund{value: msg.value}(); | ||||||||||
function _fund(uint256 _value) internal { | ||||||||||
stakingVault.fund{value: _value}(); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
|
@@ -465,20 +498,6 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
stakingVault.requestValidatorExit(_validatorPublicKey); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @dev Deposits validators to the beacon chain | ||||||||||
* @param _numberOfDeposits Number of validator deposits | ||||||||||
* @param _pubkeys Concatenated public keys of the validators | ||||||||||
* @param _signatures Concatenated signatures of the validators | ||||||||||
*/ | ||||||||||
function _depositToBeaconChain( | ||||||||||
uint256 _numberOfDeposits, | ||||||||||
bytes calldata _pubkeys, | ||||||||||
bytes calldata _signatures | ||||||||||
) internal { | ||||||||||
stakingVault.depositToBeaconChain(_numberOfDeposits, _pubkeys, _signatures); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
* @dev Mints stETH tokens backed by the vault to a recipient | ||||||||||
* @param _recipient Address of the recipient | ||||||||||
|
@@ -492,8 +511,9 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
* @dev Burns stETH tokens from the sender backed by the vault | ||||||||||
* @param _amountOfShares Amount of tokens to burn | ||||||||||
*/ | ||||||||||
function _burn(uint256 _amountOfShares) internal { | ||||||||||
STETH.transferSharesFrom(msg.sender, address(vaultHub), _amountOfShares); | ||||||||||
function _burn(address _sender, uint256 _amountOfShares) internal { | ||||||||||
STETH.transferSharesFrom(_sender, address(vaultHub), _amountOfShares); | ||||||||||
|
||||||||||
vaultHub.burnSharesBackedByVault(address(stakingVault), _amountOfShares); | ||||||||||
} | ||||||||||
|
||||||||||
|
@@ -502,7 +522,8 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
* @param _valuation custom vault valuation | ||||||||||
*/ | ||||||||||
function _totalMintableShares(uint256 _valuation) internal view returns (uint256) { | ||||||||||
uint256 maxMintableStETH = (_valuation * (TOTAL_BASIS_POINTS - vaultSocket().reserveRatioBP)) / TOTAL_BASIS_POINTS; | ||||||||||
uint256 maxMintableStETH = (_valuation * (TOTAL_BASIS_POINTS - vaultSocket().reserveRatioBP)) / | ||||||||||
TOTAL_BASIS_POINTS; | ||||||||||
return Math256.min(STETH.getSharesByPooledEth(maxMintableStETH), vaultSocket().shareLimit); | ||||||||||
} | ||||||||||
|
||||||||||
|
@@ -519,6 +540,18 @@ contract Dashboard is AccessControlEnumerable { | |||||||||
/// @notice Emitted when the contract is initialized | ||||||||||
event Initialized(); | ||||||||||
|
||||||||||
/// @notice Emitted when the ERC20 `token` or Ether is recovered (i.e. transferred) | ||||||||||
/// @param to The address of the recovery recipient | ||||||||||
/// @param token The address of the recovered ERC20 token (zero address for Ether) | ||||||||||
/// @param amount The amount of the token recovered | ||||||||||
event ERC20Recovered(address indexed to, address indexed token, uint256 amount); | ||||||||||
|
||||||||||
/// @notice Emitted when the ERC721-compatible `token` (NFT) recovered (i.e. transferred) | ||||||||||
/// @param to The address of the recovery recipient | ||||||||||
/// @param token The address of the recovered ERC721 token | ||||||||||
/// @param tokenId id of token recovered | ||||||||||
event ERC721Recovered(address indexed to, address indexed token, uint256 tokenId); | ||||||||||
|
||||||||||
// ==================== Errors ==================== | ||||||||||
|
||||||||||
/// @notice Error for zero address arguments | ||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thresholdReserveRatio vs reserveRatioThreshold is a bit weird