Skip to content

Commit 28fd8d1

Browse files
committed
v1.3 updates
1 parent e5aaadc commit 28fd8d1

16 files changed

+345
-142
lines changed

contracts/Delegation/OperatorDelegator.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ contract OperatorDelegator is
225225
);
226226

227227
// Send tokens to the specified address
228+
// TODO: do not user balance of
228229
_token.safeTransfer(_sendToAddress, _token.balanceOf(address(this)));
229230
}
230231

@@ -239,6 +240,8 @@ contract OperatorDelegator is
239240
function getStakedETHBalance() external view returns (uint256) {
240241
// TODO: Once withdrawals are enabled, allow this to handle pending withdraws and a potential negative share balance in the EigenPodManager ownershares
241242
// TODO: Once upgraded to M2, add back in staked verified ETH, e.g. + uint256(strategyManager.stakerStrategyShares(address(this), strategyManager.beaconChainETHStrategy()))
243+
// TODO: once M2 is released, there is a possibility someone could call Verify() to try and mess up the TVL calcs (we would double count the stakedButNotVerifiedEth + actual verified ETH in the EigenPod)
244+
// - we should track the validator node's verified status to ensure this doesn't happen
242245
return stakedButNotVerifiedEth + address(eigenPod).balance;
243246
}
244247

contracts/Errors/Errors.sol

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,16 @@ error OraclePriceExpired();
7171
error MismatchedArrayLengths();
7272

7373
/// @dev Error when caller does not have Deposit Withdraw Pauser role
74-
error NotDepositWithdrawPauser();
74+
error NotDepositWithdrawPauser();
75+
76+
/// @dev Error when an individual token TVL is over the max
77+
error MaxTokenTVLReached();
78+
79+
/// @dev Error when Oracle price is invalid
80+
error InvalidOraclePrice();
81+
82+
/// @dev Error when calling an invalid function
83+
error NotImplemented();
84+
85+
/// @dev Error when calculating token amounts is invalid
86+
error InvalidTokenAmount();

contracts/IRestakeManager.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,9 @@ interface IRestakeManager {
1111
uint256 _amount
1212
) external;
1313
function depositQueue() external view returns (IDepositQueue);
14+
15+
function calculateTVLs()
16+
external
17+
view
18+
returns (uint256[][] memory, uint256[] memory, uint256);
1419
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.19;
3+
4+
/// @dev Interface to get exchange rate on wBETH
5+
interface IStakedTokenV2 {
6+
function exchangeRate() external view returns (uint256 _exchangeRate);
7+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.19;
3+
4+
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
5+
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
6+
import "./WBETHShimStorage.sol";
7+
import "../../Errors/Errors.sol";
8+
9+
/**
10+
* @title WBETHShim
11+
* @dev The contract hard codes the decimals to 18 decimals and returns the conversion rate of 1 mETH to ETH underlying the token in the wBETH protocol
12+
* @notice This contract is a shim that implements the Chainlink AggregatorV3Interface and returns pricing from the wBETH token contract
13+
*/
14+
15+
contract WBETHShim is
16+
Initializable,
17+
WBETHShimStorageV1
18+
{
19+
/// @dev Prevents implementation contract from being initialized.
20+
/// @custom:oz-upgrades-unsafe-allow constructor
21+
constructor() {
22+
_disableInitializers();
23+
}
24+
25+
/// @dev Initializes the contract with initial vars
26+
function initialize(IStakedTokenV2 _wBETHToken) public initializer {
27+
if(address(_wBETHToken) == address(0x0)) revert InvalidZeroInput();
28+
29+
wBETHToken = _wBETHToken;
30+
}
31+
32+
function decimals() external pure returns (uint8){
33+
return 18;
34+
}
35+
36+
function description() external pure returns (string memory){
37+
return "wBETH Chainlink Shim";
38+
}
39+
40+
function version() external pure returns (uint256){
41+
return 1;
42+
}
43+
44+
/// @dev Historical data not available
45+
function getRoundData(
46+
uint80
47+
) external pure returns (uint80, int256, uint256, uint256, uint80){
48+
revert NotImplemented();
49+
}
50+
51+
function latestRoundData()
52+
external
53+
view
54+
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound){
55+
return _getWBETHData();
56+
}
57+
58+
59+
/**
60+
* @notice This function gets the price of 1 mETH in ETH from the mETH staking contract with 18 decimal precision
61+
* @dev This function does not implement the full Chainlink AggregatorV3Interface
62+
* @return roundId 0 - never returns valid round ID
63+
* @return answer The conversion rate of 1 mETH to ETH.
64+
* @return startedAt 0 - never returns valid timestamp
65+
* @return updatedAt The current timestamp.
66+
* @return answeredInRound 0 - never returns valid round ID
67+
*/
68+
function _getWBETHData() internal view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound){
69+
return (
70+
0,
71+
int256(wBETHToken.exchangeRate()),
72+
0,
73+
block.timestamp,
74+
0
75+
);
76+
}
77+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.19;
3+
4+
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
5+
import "./IStakedTokenV2.sol";
6+
7+
abstract contract WBETHShimStorageV1 is AggregatorV3Interface{
8+
IStakedTokenV2 public wBETHToken;
9+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.19;
3+
4+
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5+
6+
interface IMethStaking {
7+
function mETHToETH(uint256 mETHAmount) external view returns (uint256);
8+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.19;
3+
4+
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
5+
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
6+
import "./METHShimStorage.sol";
7+
import "../../Errors/Errors.sol";
8+
9+
/**
10+
* @title METHShim
11+
* @dev The contract hard codes the decimals to 18 decimals and returns the conversion rate of 1 mETH to ETH underlying the token in the mETH protocol
12+
* @notice This contract is a shim that implements the Chainlink AggregatorV3Interface and returns pricing from the mETH staking contract
13+
*/
14+
15+
contract METHShim is
16+
Initializable,
17+
METHShimStorageV1
18+
{
19+
/// @dev Prevents implementation contract from being initialized.
20+
/// @custom:oz-upgrades-unsafe-allow constructor
21+
constructor() {
22+
_disableInitializers();
23+
}
24+
25+
/// @dev Initializes the contract with initial vars
26+
function initialize(IMethStaking _methStaking) public initializer {
27+
if(address(_methStaking) == address(0x0)) revert InvalidZeroInput();
28+
29+
methStaking = _methStaking;
30+
}
31+
32+
function decimals() external pure returns (uint8){
33+
return 18;
34+
}
35+
36+
function description() external pure returns (string memory){
37+
return "METH Chainlink Shim";
38+
}
39+
40+
function version() external pure returns (uint256){
41+
return 1;
42+
}
43+
44+
/// @dev Historical data not available
45+
function getRoundData(
46+
uint80
47+
) external pure returns (uint80, int256, uint256, uint256, uint80){
48+
revert NotImplemented();
49+
}
50+
51+
function latestRoundData()
52+
external
53+
view
54+
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound){
55+
return _getMETHData();
56+
}
57+
58+
59+
/**
60+
* @notice This function gets the price of 1 mETH in ETH from the mETH staking contract with 18 decimal precision
61+
* @dev This function does not implement the full Chainlink AggregatorV3Interface
62+
* @return roundId 0 - never returns valid round ID
63+
* @return answer The conversion rate of 1 mETH to ETH.
64+
* @return startedAt 0 - never returns valid timestamp
65+
* @return updatedAt The current timestamp.
66+
* @return answeredInRound 0 - never returns valid round ID
67+
*/
68+
function _getMETHData() internal view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound){
69+
return (
70+
0,
71+
int256(methStaking.mETHToETH(1 ether)),
72+
0,
73+
block.timestamp,
74+
0
75+
);
76+
}
77+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity 0.8.19;
3+
4+
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
5+
import "./IMethStaking.sol";
6+
7+
abstract contract METHShimStorageV1 is AggregatorV3Interface{
8+
IMethStaking public methStaking;
9+
}

contracts/Oracle/RenzoOracle.sol

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ contract RenzoOracle is
7070

7171
(, int256 price, , uint256 timestamp, ) = oracle.latestRoundData();
7272
if(timestamp < block.timestamp - MAX_TIME_WINDOW) revert OraclePriceExpired();
73+
if(price <= 0) revert InvalidOraclePrice();
7374

7475
// Price is times 10**18 ensure value amount is scaled
7576
return uint256(price) * _balance / SCALE_FACTOR;
@@ -83,6 +84,7 @@ contract RenzoOracle is
8384

8485
(, int256 price, , uint256 timestamp, ) = oracle.latestRoundData();
8586
if(timestamp < block.timestamp - MAX_TIME_WINDOW) revert OraclePriceExpired();
87+
if(price <= 0) revert InvalidOraclePrice();
8688

8789
// Price is times 10**18 ensure token amount is scaled
8890
return _value * SCALE_FACTOR / uint256(price);
@@ -120,12 +122,22 @@ contract RenzoOracle is
120122
uint256 newEzETHSupply = (_existingEzETHSupply * SCALE_FACTOR) / (SCALE_FACTOR - inflationPercentaage);
121123

122124
// Subtract the old supply from the new supply to get the amount to mint
123-
return newEzETHSupply - _existingEzETHSupply;
125+
uint256 mintAmount = newEzETHSupply - _existingEzETHSupply;
126+
127+
// Sanity check
128+
if(mintAmount == 0) revert InvalidTokenAmount();
129+
130+
return mintAmount;
124131
}
125132

126133
// Given the amount of ezETH to burn, the supply of ezETH, and the total value in the protocol, determine amount of value to return to user
127134
function calculateRedeemAmount(uint256 _ezETHBeingBurned, uint256 _existingEzETHSupply, uint256 _currentValueInProtocol) external pure returns (uint256) {
128135
// This is just returning the percentage of TVL that matches the percentage of ezETH being burned
129-
return (_currentValueInProtocol * _ezETHBeingBurned) / _existingEzETHSupply;
136+
uint256 redeemAmount = (_currentValueInProtocol * _ezETHBeingBurned) / _existingEzETHSupply;
137+
138+
// Sanity check
139+
if(redeemAmount == 0) revert InvalidTokenAmount();
140+
141+
return redeemAmount;
130142
}
131143
}

0 commit comments

Comments
 (0)