-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: accounting for PR comments
- Loading branch information
Showing
4 changed files
with
99 additions
and
126 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 |
---|---|---|
@@ -1,8 +1,9 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.25; | ||
|
||
import {GenericBondCalculator} from "./GenericBondCalculator.sol"; | ||
import {mulDiv} from "@prb/math/src/Common.sol"; | ||
import {IVotingEscrow} from "./interfaces/IVotingEscrow.sol"; | ||
import "./interfaces/IUniswapV2Pair.sol"; | ||
|
||
interface ITokenomics { | ||
/// @dev Gets number of new units that were donated in the last epoch. | ||
|
@@ -63,12 +64,16 @@ struct Product { | |
/// @author Aleksandr Kuperman - <[email protected]> | ||
/// @author Andrey Lebedev - <[email protected]> | ||
/// @author Mariapia Moscatiello - <[email protected]> | ||
contract BondCalculator is GenericBondCalculator { | ||
contract BondCalculator { | ||
event OwnerUpdated(address indexed owner); | ||
event DiscountParamsUpdated(DiscountParams newDiscountParams); | ||
|
||
// Maximum sum of discount factor weights | ||
uint256 public constant MAX_SUM_WEIGHTS = 10_000; | ||
// OLAS contract address | ||
address public immutable olas; | ||
// Tokenomics contract address | ||
address public immutable tokenomics; | ||
// veOLAS contract address | ||
address public immutable ve; | ||
|
||
|
@@ -83,14 +88,14 @@ contract BondCalculator is GenericBondCalculator { | |
/// @param _tokenomics Tokenomics contract address. | ||
/// @param _ve veOLAS contract address. | ||
/// @param _discountParams Discount factor parameters. | ||
constructor(address _olas, address _tokenomics, address _ve, DiscountParams memory _discountParams) | ||
GenericBondCalculator(_olas, _tokenomics) | ||
{ | ||
// Check for zero address | ||
if (_ve == address(0)) { | ||
constructor(address _olas, address _tokenomics, address _ve, DiscountParams memory _discountParams) { | ||
// Check for at least one zero contract address | ||
if (_olas == address(0) || _tokenomics == address(0) || _ve == address(0)) { | ||
revert ZeroAddress(); | ||
} | ||
|
||
olas = _olas; | ||
tokenomics = _tokenomics; | ||
ve = _ve; | ||
owner = msg.sender; | ||
|
||
|
@@ -153,17 +158,14 @@ contract BondCalculator is GenericBondCalculator { | |
} | ||
|
||
/// @dev Calculated inverse discount factor based on bonding and account parameters. | ||
/// @param data Custom data that is used to calculate the IDF: | ||
/// - account Account address. | ||
/// - bondVestingTime Bond vesting time. | ||
/// - productMaxVestingTime Product max vesting time. | ||
/// - productSupply Current product supply. | ||
/// - productPayout Current product payout. | ||
/// @param account Account address. | ||
/// @param bondVestingTime Bond vesting time. | ||
/// @param productMaxVestingTime Product max vesting time. | ||
/// @param productSupply Current product supply. | ||
/// @param productPayout Current product payout. | ||
/// @return idf Inverse discount factor in 18 decimals format. | ||
function calculateIDF(bytes memory data) public view override returns (uint256 idf) { | ||
// Decode the required data | ||
(address account, uint256 bondVestingTime, uint256 productMaxVestingTime, uint256 productSupply, | ||
uint256 productPayout) = abi.decode(data, (address, uint256, uint256, uint256, uint256)); | ||
function calculateIDF(address account, uint256 bondVestingTime, uint256 productMaxVestingTime, uint256 productSupply, | ||
uint256 productPayout) public view returns (uint256 idf) { | ||
|
||
// Get the copy of the discount params | ||
DiscountParams memory localParams = discountParams; | ||
|
@@ -226,6 +228,73 @@ contract BondCalculator is GenericBondCalculator { | |
idf = 1e18 + discountBooster; | ||
} | ||
|
||
/// @dev Calculates the amount of OLAS tokens based on the bonding calculator mechanism accounting for dynamic IDF. | ||
/// @param account Account address. | ||
/// @param tokenAmount LP token amount. | ||
/// @param priceLP LP token price. | ||
/// @param bondVestingTime Bond vesting time. | ||
/// @param productMaxVestingTime Product max vesting time. | ||
/// @param productSupply Current product supply. | ||
/// @param productPayout Current product payout. | ||
/// @return amountOLAS Resulting amount of OLAS tokens. | ||
function calculatePayoutOLAS( | ||
address account, | ||
uint256 tokenAmount, | ||
uint256 priceLP, | ||
uint256 bondVestingTime, | ||
uint256 productMaxVestingTime, | ||
uint256 productSupply, | ||
uint256 productPayout | ||
) external view returns (uint256 amountOLAS) { | ||
// The result is divided by additional 1e18, since it was multiplied by in the current LP price calculation | ||
// The resulting amountDF can not overflow by the following calculations: idf = 64 bits; | ||
// priceLP = 2 * r0/L * 10^18 = 2*r0*10^18/sqrt(r0*r1) ~= 61 + 96 - sqrt(96 * 112) ~= 53 bits (if LP is balanced) | ||
// or 2* r0/sqrt(r0) * 10^18 => 87 bits + 60 bits = 147 bits (if LP is unbalanced); | ||
// tokenAmount is of the order of sqrt(r0*r1) ~ 104 bits (if balanced) or sqrt(96) ~ 10 bits (if max unbalanced); | ||
// overall: 64 + 53 + 104 = 221 < 256 - regular case if LP is balanced, and 64 + 147 + 10 = 221 < 256 if unbalanced | ||
// mulDiv will correctly fit the total amount up to the value of max uint256, i.e., max of priceLP and max of tokenAmount, | ||
// however their multiplication can not be bigger than the max of uint192 | ||
uint256 totalTokenValue = mulDiv(priceLP, tokenAmount, 1); | ||
// Check for the cumulative LP tokens value limit | ||
if (totalTokenValue > type(uint192).max) { | ||
revert Overflow(totalTokenValue, type(uint192).max); | ||
} | ||
|
||
// Calculate the dynamic inverse discount factor | ||
uint256 idf = calculateIDF(account, bondVestingTime, productMaxVestingTime, productSupply, productPayout); | ||
|
||
// Amount with the discount factor is IDF * priceLP * tokenAmount / 1e36 | ||
// At this point of time IDF is bound by the max of uint64, and totalTokenValue is no bigger than the max of uint192 | ||
amountOLAS = (idf * totalTokenValue) / 1e36; | ||
} | ||
|
||
/// @dev Gets current reserves of OLAS / totalSupply of Uniswap V2-like LP tokens. | ||
/// @notice The price LP calculation is based on the UniswapV2Pair contract. | ||
/// @param token Token address. | ||
/// @return priceLP Resulting reserveX / totalSupply ratio with 18 decimals. | ||
function getCurrentPriceLP(address token) external view returns (uint256 priceLP) { | ||
IUniswapV2Pair pair = IUniswapV2Pair(token); | ||
uint256 totalSupply = pair.totalSupply(); | ||
if (totalSupply > 0) { | ||
address token0 = pair.token0(); | ||
address token1 = pair.token1(); | ||
uint256 reserve0; | ||
uint256 reserve1; | ||
// requires low gas | ||
(reserve0, reserve1, ) = pair.getReserves(); | ||
// token0 != olas && token1 != olas, this should never happen | ||
if (token0 == olas || token1 == olas) { | ||
// If OLAS is in token0, assign its reserve to reserve1, otherwise the reserve1 is already correct | ||
if (token0 == olas) { | ||
reserve1 = reserve0; | ||
} | ||
// Calculate the LP price based on reserves and totalSupply ratio multiplied by 1e18 | ||
// Inspired by: https://github.com/curvefi/curve-contract/blob/master/contracts/pool-templates/base/SwapTemplateBase.vy#L262 | ||
priceLP = (reserve1 * 1e18) / totalSupply; | ||
} | ||
} | ||
} | ||
|
||
function getDiscountParams() external view returns (DiscountParams memory) { | ||
return discountParams; | ||
} | ||
|
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 was deleted.
Oops, something went wrong.
File renamed without changes.