-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a28cbe9
commit e599acd
Showing
10 changed files
with
542 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,9 @@ broadcast | |
node_modules/ | ||
yarn-error.log | ||
|
||
# Hardhat | ||
artifacts/ | ||
|
||
# random files on MacOs | ||
.DS_Store | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity 0.8.20; | ||
|
||
import { MultiRolesAuthority } from "solmate/auth/authorities/MultiRolesAuthority.sol"; | ||
import { FixedPointMath } from "../src/libraries/FixedPointMath.sol"; | ||
import { ERC20Mintable } from "./ERC20Mintable.sol"; | ||
import { IERC20 } from "../src/interfaces/IERC20.sol"; | ||
import { IRestakeManager, IRenzoOracle } from "../src/interfaces/IRenzo.sol"; | ||
|
||
/// @author DELV | ||
/// @title MockLido | ||
/// @notice This mock yield source will accrue interest at a specified rate | ||
/// Every stateful interaction will accrue interest, so the interest | ||
/// accrual will approximate continuous compounding as the contract | ||
/// is called more frequently. | ||
/// @custom:disclaimer The language used in this code is for coding convenience | ||
/// only, and is not intended to, and does not, have any | ||
/// particular legal or regulatory significance. | ||
contract MockEzEthPool is | ||
IRestakeManager, | ||
IRenzoOracle, | ||
MultiRolesAuthority, | ||
ERC20Mintable | ||
{ | ||
using FixedPointMath for uint256; | ||
|
||
// Interest State | ||
uint256 internal _rate; | ||
uint256 internal _lastUpdated; | ||
|
||
// Lido State | ||
uint256 totalPooledEther; | ||
uint256 totalShares; | ||
|
||
constructor( | ||
uint256 _initialRate, | ||
address _admin, | ||
bool _isCompetitionMode, | ||
uint256 _maxMintAmount | ||
) | ||
ERC20Mintable( | ||
"Renzo ezETH", | ||
"ezETH", | ||
18, | ||
_admin, | ||
_isCompetitionMode, | ||
_maxMintAmount | ||
) | ||
{ | ||
_rate = _initialRate; | ||
_lastUpdated = block.timestamp; | ||
} | ||
|
||
/// Overrides /// | ||
|
||
function submit(address) external payable returns (uint256) { | ||
// Accrue interest. | ||
_accrue(); | ||
|
||
// If this is the first deposit, mint shares 1:1. | ||
if (getTotalShares() == 0) { | ||
totalShares = msg.value; | ||
totalPooledEther = msg.value; | ||
_mint(msg.sender, msg.value); | ||
return msg.value; | ||
} | ||
|
||
// Calculate the amount of stETH shares that should be minted. | ||
uint256 shares = msg.value.mulDivDown( | ||
getTotalShares(), | ||
getTotalPooledEther() | ||
); | ||
|
||
// Update the Lido state. | ||
totalPooledEther += msg.value; | ||
totalShares += shares; | ||
|
||
// Mint the stETH tokens to the user. | ||
_mint(msg.sender, msg.value); | ||
|
||
return shares; | ||
} | ||
|
||
function transferShares( | ||
address _recipient, | ||
uint256 _sharesAmount | ||
) external returns (uint256) { | ||
// Accrue interest. | ||
_accrue(); | ||
|
||
// Calculate the amount of tokens that should be transferred. | ||
uint256 tokenAmount = _sharesAmount.mulDivDown( | ||
getTotalPooledEther(), | ||
getTotalShares() | ||
); | ||
|
||
// Transfer the tokens to the user. | ||
transfer(_recipient, tokenAmount); | ||
|
||
return tokenAmount; | ||
} | ||
|
||
function transferSharesFrom( | ||
address _sender, | ||
address _recipient, | ||
uint256 _sharesAmount | ||
) external returns (uint256) { | ||
// Accrue interest. | ||
_accrue(); | ||
|
||
// Calculate the amount of tokens that should be transferred. | ||
uint256 tokenAmount = _sharesAmount.mulDivDown( | ||
getTotalPooledEther(), | ||
getTotalShares() | ||
); | ||
|
||
// Transfer the tokens to the user. | ||
transferFrom(_sender, _recipient, tokenAmount); | ||
|
||
return tokenAmount; | ||
} | ||
|
||
function getSharesByPooledEth( | ||
uint256 _ethAmount | ||
) external view returns (uint256) { | ||
return _ethAmount.mulDivDown(getTotalShares(), getTotalPooledEther()); | ||
} | ||
|
||
function getPooledEthByShares( | ||
uint256 _sharesAmount | ||
) public view returns (uint256) { | ||
return | ||
_sharesAmount.mulDivDown(getTotalPooledEther(), getTotalShares()); | ||
} | ||
|
||
function getBufferedEther() external pure returns (uint256) { | ||
return 0; | ||
} | ||
|
||
function getTotalPooledEther() public view returns (uint256) { | ||
return totalPooledEther + _getAccruedInterest(); | ||
} | ||
|
||
function getTotalShares() public view returns (uint256) { | ||
return totalShares; | ||
} | ||
|
||
function sharesOf(address _account) external view returns (uint256) { | ||
uint256 tokenBalance = balanceOf[_account]; | ||
return tokenBalance.mulDivDown(getTotalShares(), getTotalPooledEther()); | ||
} | ||
|
||
/// Mock /// | ||
|
||
function setRate(uint256 _rate_) external requiresAuthDuringCompetition { | ||
_accrue(); | ||
_rate = _rate_; | ||
} | ||
|
||
function getRate() external view returns (uint256) { | ||
return _rate; | ||
} | ||
|
||
function _accrue() internal { | ||
uint256 interest = _getAccruedInterest(); | ||
if (interest > 0) { | ||
totalPooledEther += interest; | ||
} | ||
_lastUpdated = block.timestamp; | ||
} | ||
|
||
function _getAccruedInterest() internal view returns (uint256) { | ||
if (_rate == 0) { | ||
return 0; | ||
} | ||
|
||
// base_balance = base_balance * (1 + r * t) | ||
uint256 timeElapsed = (block.timestamp - _lastUpdated).divDown( | ||
365 days | ||
); | ||
uint256 accrued = totalPooledEther.mulDown(_rate.mulDown(timeElapsed)); | ||
return accrued; | ||
} | ||
|
||
function calculateTVLs() | ||
public | ||
view | ||
override | ||
returns (uint256[][] memory, uint256[] memory, uint256) | ||
{ | ||
uint256[][] memory operator_tokens_tvls; | ||
uint256[] memory operator_tvls; | ||
uint256 tvl = getTotalPooledEther(); | ||
return (operator_tokens_tvls, operator_tvls, tvl); | ||
} | ||
|
||
function depositETH() external payable { | ||
revert("depositETH: Not Implemented"); | ||
} | ||
|
||
function ezETH() external view returns (address) { | ||
return address(this); | ||
} | ||
|
||
function renzoOracle() external view returns (address) { | ||
return address(this); | ||
} | ||
|
||
// Renzo Oracle Functions // | ||
|
||
function lookupTokenValue( | ||
IERC20, //_token, | ||
uint256 //_balance | ||
) external pure returns (uint256) { | ||
revert("lookupTokenValue: Not Implemented"); | ||
} | ||
|
||
function lookupTokenAmountFromValue( | ||
IERC20, // _token, | ||
uint256 // _value | ||
) external pure returns (uint256) { | ||
revert("lookupTokenValue: Not Implemented"); | ||
} | ||
|
||
function lookupTokenValues( | ||
IERC20[] memory, // _tokens, | ||
uint256[] memory // _balances | ||
) external pure returns (uint256) { | ||
revert("lookupTokenValue: Not Implemented"); | ||
} | ||
|
||
function calculateMintAmount( | ||
uint256, // _currentValueInProtocol, | ||
uint256, // _newValueAdded, | ||
uint256 // _existingEzETHSupply | ||
) external pure returns (uint256) { | ||
revert("lookupTokenValue: Not Implemented"); | ||
} | ||
|
||
function calculateRedeemAmount( | ||
uint256 _ezETHBeingBurned, | ||
uint256, // _existingEzETHSupply, | ||
uint256 // _currentValueInProtocol | ||
) public view returns (uint256) { | ||
return getPooledEthByShares(_ezETHBeingBurned); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.