-
Notifications
You must be signed in to change notification settings - Fork 0
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
Showing
2 changed files
with
174 additions
and
0 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
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,170 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity 0.8.19; | ||
|
||
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; | ||
import {IMysoTokenManager} from "../peer-to-peer/interfaces/oracles/IMysoTokenManager.sol"; | ||
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; | ||
import {LogExpMath} from "../peer-to-peer/oracles/custom/utils/LogExpMath.sol"; | ||
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; | ||
|
||
/** | ||
* @dev supports oracles which are compatible with v2v3 or v3 interfaces | ||
*/ | ||
contract TestnetMysoOracle is Ownable { | ||
struct PriceParams { | ||
// maxPrice is in 8 decimals for chainlink consistency | ||
uint96 maxPrice; | ||
// k is in 18 decimals | ||
// e.g. 8e17 is 0.8 in decimal | ||
uint96 k; | ||
// a and b are in terms of 1000 | ||
// e.g. 1770 is 1.77 in decimal | ||
uint32 a; | ||
uint32 b; | ||
} | ||
// solhint-disable var-name-mixedcase | ||
address internal constant MYSO = 0x8fF1307ba7e5FDc3A411d259bAe641e2B1d897c4; // myso sepolia address | ||
address internal constant WETH = 0x3564c06EfEe0FeB0af5EF59dc5440bC45A265dA5; | ||
address internal constant USDC = 0x2296282e2e2a4158140E3b4B99855ADa4a06a4B8; | ||
address internal constant USDT = 0xdc2E37A79Ee93906c4665e49f82C1b895dFc7092; | ||
address internal constant DAI = 0x40aD85ab1aA2a5bA61a2a026cfe1F4fd859eA188; | ||
|
||
uint256 internal constant MYSO_PRICE_TIME_LOCK = 5 minutes; | ||
|
||
address public mysoTokenManager; | ||
|
||
PriceParams public mysoPriceParams; | ||
|
||
event MysoTokenManagerUpdated(address newMysoTokenManager); | ||
|
||
error NoMyso(); | ||
error NoOracle(); | ||
|
||
/** | ||
* @dev constructor for TestMysoOracle | ||
* @param _owner owner of the contract | ||
* @param _mysoTokenManager address of myso token manager contract | ||
* @param _maxPrice max price in 8 decimals | ||
* @param _k k in 18 decimals | ||
* @param _a a in terms of 1000 | ||
* @param _b b in terms of 1000 | ||
*/ | ||
constructor( | ||
address _owner, | ||
address _mysoTokenManager, | ||
uint96 _maxPrice, | ||
uint96 _k, | ||
uint32 _a, | ||
uint32 _b | ||
) Ownable() { | ||
mysoTokenManager = _mysoTokenManager; | ||
mysoPriceParams = PriceParams(_maxPrice, _k, _a, _b); | ||
_transferOwnership(_owner); | ||
} | ||
|
||
/** | ||
* @dev updates myso token manager contract address | ||
* @param _newMysoTokenManager new myso token manager contract address | ||
*/ | ||
|
||
function setMysoTokenManager( | ||
address _newMysoTokenManager | ||
) external onlyOwner { | ||
mysoTokenManager = _newMysoTokenManager; | ||
emit MysoTokenManagerUpdated(_newMysoTokenManager); | ||
} | ||
|
||
/** | ||
* @dev updates myso price params | ||
* @param _maxPrice max price in 8 decimals | ||
* @param _k k in 18 decimals | ||
* @param _a a in terms of 1000 | ||
* @param _b b in terms of 1000 | ||
*/ | ||
function setMysoPriceParams( | ||
uint96 _maxPrice, | ||
uint96 _k, | ||
uint32 _a, | ||
uint32 _b | ||
) external onlyOwner { | ||
mysoPriceParams = PriceParams(_maxPrice, _k, _a, _b); | ||
} | ||
|
||
function getPrice( | ||
address collToken, | ||
address loanToken | ||
) external view returns (uint256 collTokenPriceInLoanToken) { | ||
(uint256 priceOfCollToken, uint256 priceOfLoanToken) = getRawPrices( | ||
collToken, | ||
loanToken | ||
); | ||
uint256 loanTokenDecimals = (loanToken == MYSO) | ||
? 18 | ||
: IERC20Metadata(loanToken).decimals(); | ||
collTokenPriceInLoanToken = | ||
(priceOfCollToken * 10 ** loanTokenDecimals) / | ||
priceOfLoanToken; | ||
} | ||
|
||
function getRawPrices( | ||
address collToken, | ||
address loanToken | ||
) | ||
public | ||
view | ||
returns (uint256 collTokenPriceRaw, uint256 loanTokenPriceRaw) | ||
{ | ||
// must have at least one token is MYSO to use this oracle | ||
if (collToken != MYSO && loanToken != MYSO) { | ||
revert NoMyso(); | ||
} | ||
(collTokenPriceRaw, loanTokenPriceRaw) = ( | ||
_getPriceOfToken(collToken), | ||
_getPriceOfToken(loanToken) | ||
); | ||
} | ||
|
||
function _getPriceOfToken( | ||
address token | ||
) internal view virtual returns (uint256 tokenPriceRaw) { | ||
if (token == MYSO) { | ||
tokenPriceRaw = _getMysoPriceInEth(); | ||
} else if (token == WETH) { | ||
tokenPriceRaw = 1e18; | ||
} else if (token == USDC || token == USDT || token == DAI) { | ||
tokenPriceRaw = Math.mulDiv(1e8, 1e18, 3300 * 1e8); | ||
} else { | ||
revert NoOracle(); | ||
} | ||
} | ||
|
||
function _getMysoPriceInEth() | ||
internal | ||
view | ||
returns (uint256 mysoPriceInEth) | ||
{ | ||
uint256 ethPriceInUsd = 3300 * 1e8; | ||
uint256 _totalMysoLoanAmount = IMysoTokenManager(mysoTokenManager) | ||
.totalMysoLoanAmount(); | ||
uint256 mysoPriceInUsd = _getMysoPriceInUsd(_totalMysoLoanAmount); | ||
mysoPriceInEth = Math.mulDiv(mysoPriceInUsd, 1e18, ethPriceInUsd); | ||
} | ||
|
||
function _getMysoPriceInUsd( | ||
uint256 totalMysoLoanAmount | ||
) internal view returns (uint256 mysoPriceInUsd) { | ||
PriceParams memory params = mysoPriceParams; | ||
uint256 maxPrice = uint256(params.maxPrice); | ||
uint256 k = uint256(params.k); | ||
uint256 a = uint256(params.a); | ||
uint256 b = uint256(params.b); | ||
uint256 numerator = k * b; | ||
uint256 denominator = uint256( | ||
LogExpMath.exp( | ||
int256(Math.mulDiv(totalMysoLoanAmount, a, 1000000000)) | ||
) | ||
) + (2 * b - 1000) * 1e15; | ||
mysoPriceInUsd = maxPrice - Math.mulDiv(numerator, 1e5, denominator); | ||
} | ||
} |