文件 1 的 17:CastU128I128.sol
pragma solidity ^0.8.0;
library CastU128I128 {
function i128(uint128 x) internal pure returns (int128 y) {
require (x <= uint128(type(int128).max), "Cast overflow");
y = int128(x);
}
}
文件 2 的 17:CastU128U112.sol
pragma solidity ^0.8.0;
library CastU128U112 {
function u112(uint128 x) internal pure returns (uint112 y) {
require (x <= uint128(type(uint112).max), "Cast overflow");
y = uint112(x);
}
}
文件 3 的 17:CastU256I256.sol
pragma solidity ^0.8.0;
library CastU256I256 {
function i256(uint256 x) internal pure returns (int256 y) {
require (x <= uint256(type(int256).max), "Cast overflow");
y = int256(x);
}
}
文件 4 的 17:CastU256U112.sol
pragma solidity ^0.8.0;
library CastU256U112 {
function u112(uint256 x) internal pure returns (uint112 y) {
require (x <= type(uint112).max, "Cast overflow");
y = uint112(x);
}
}
文件 5 的 17:CastU256U128.sol
pragma solidity ^0.8.0;
library CastU256U128 {
function u128(uint256 x) internal pure returns (uint128 y) {
require (x <= type(uint128).max, "Cast overflow");
y = uint128(x);
}
}
文件 6 的 17:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20Metadata.sol";
contract ERC20 is IERC20Metadata {
uint256 internal _totalSupply;
mapping (address => uint256) internal _balanceOf;
mapping (address => mapping (address => uint256)) internal _allowance;
string public override name = "???";
string public override symbol = "???";
uint8 public override decimals = 18;
constructor(string memory name_, string memory symbol_, uint8 decimals_) {
name = name_;
symbol = symbol_;
decimals = decimals_;
}
function totalSupply() external view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address guy) external view virtual override returns (uint256) {
return _balanceOf[guy];
}
function allowance(address owner, address spender) external view virtual override returns (uint256) {
return _allowance[owner][spender];
}
function approve(address spender, uint wad) external virtual override returns (bool) {
return _setAllowance(msg.sender, spender, wad);
}
function transfer(address dst, uint wad) external virtual override returns (bool) {
return _transfer(msg.sender, dst, wad);
}
function transferFrom(address src, address dst, uint wad) external virtual override returns (bool) {
_decreaseAllowance(src, wad);
return _transfer(src, dst, wad);
}
function _transfer(address src, address dst, uint wad) internal virtual returns (bool) {
require(_balanceOf[src] >= wad, "ERC20: Insufficient balance");
unchecked { _balanceOf[src] = _balanceOf[src] - wad; }
_balanceOf[dst] = _balanceOf[dst] + wad;
emit Transfer(src, dst, wad);
return true;
}
function _setAllowance(address owner, address spender, uint wad) internal virtual returns (bool) {
_allowance[owner][spender] = wad;
emit Approval(owner, spender, wad);
return true;
}
function _decreaseAllowance(address src, uint wad) internal virtual returns (bool) {
if (src != msg.sender) {
uint256 allowed = _allowance[src][msg.sender];
if (allowed != type(uint).max) {
require(allowed >= wad, "ERC20: Insufficient approval");
unchecked { _setAllowance(src, msg.sender, allowed - wad); }
}
}
return true;
}
function _mint(address dst, uint wad) internal virtual returns (bool) {
_balanceOf[dst] = _balanceOf[dst] + wad;
_totalSupply = _totalSupply + wad;
emit Transfer(address(0), dst, wad);
return true;
}
function _burn(address src, uint wad) internal virtual returns (bool) {
unchecked {
require(_balanceOf[src] >= wad, "ERC20: Insufficient balance");
_balanceOf[src] = _balanceOf[src] - wad;
_totalSupply = _totalSupply - wad;
emit Transfer(src, address(0), wad);
}
return true;
}
}
文件 7 的 17:ERC20Permit.sol
pragma solidity ^0.8.0;
import "./ERC20.sol";
import "./IERC2612.sol";
abstract contract ERC20Permit is ERC20, IERC2612 {
mapping (address => uint256) public override nonces;
bytes32 public immutable PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 private immutable _DOMAIN_SEPARATOR;
uint256 public immutable deploymentChainId;
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_, decimals_) {
deploymentChainId = block.chainid;
_DOMAIN_SEPARATOR = _calculateDomainSeparator(block.chainid);
}
function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {
return keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256(bytes(version())),
chainId,
address(this)
)
);
}
function DOMAIN_SEPARATOR() external view returns (bytes32) {
return block.chainid == deploymentChainId ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(block.chainid);
}
function version() public pure virtual returns(string memory) { return "1"; }
function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external virtual override {
require(deadline >= block.timestamp, "ERC20Permit: expired deadline");
bytes32 hashStruct = keccak256(
abi.encode(
PERMIT_TYPEHASH,
owner,
spender,
amount,
nonces[owner]++,
deadline
)
);
bytes32 hash = keccak256(
abi.encodePacked(
"\x19\x01",
block.chainid == deploymentChainId ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(block.chainid),
hashStruct
)
);
address signer = ecrecover(hash, v, r, s);
require(
signer != address(0) && signer == owner,
"ERC20Permit: invalid signature"
);
_setAllowance(owner, spender, amount);
}
}
文件 8 的 17:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 9 的 17:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 10 的 17:IERC2612.sol
pragma solidity ^0.8.0;
interface IERC2612 {
function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
function nonces(address owner) external view returns (uint256);
}
文件 11 的 17:IFYToken.sol
pragma solidity ^0.8.0;
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";
interface IFYToken is IERC20 {
function underlying() external view returns (address);
function maturity() external view returns (uint256);
function mature() external;
function mintWithUnderlying(address to, uint256 amount) external;
function redeem(address to, uint256 amount) external returns (uint256);
function mint(address to, uint256 fyTokenAmount) external;
function burn(address from, uint256 fyTokenAmount) external;
}
文件 12 的 17:IPool.sol
pragma solidity >= 0.8.0;
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";
import "@yield-protocol/utils-v2/contracts/token/IERC2612.sol";
import "@yield-protocol/vault-interfaces/IFYToken.sol";
interface IPool is IERC20, IERC2612 {
function ts() external view returns(int128);
function g1() external view returns(int128);
function g2() external view returns(int128);
function maturity() external view returns(uint32);
function scaleFactor() external view returns(uint96);
function getCache() external view returns (uint112, uint112, uint32);
function base() external view returns(IERC20);
function fyToken() external view returns(IFYToken);
function getBaseBalance() external view returns(uint112);
function getFYTokenBalance() external view returns(uint112);
function retrieveBase(address to) external returns(uint128 retrieved);
function retrieveFYToken(address to) external returns(uint128 retrieved);
function sellBase(address to, uint128 min) external returns(uint128);
function buyBase(address to, uint128 baseOut, uint128 max) external returns(uint128);
function sellFYToken(address to, uint128 min) external returns(uint128);
function buyFYToken(address to, uint128 fyTokenOut, uint128 max) external returns(uint128);
function sellBasePreview(uint128 baseIn) external view returns(uint128);
function buyBasePreview(uint128 baseOut) external view returns(uint128);
function sellFYTokenPreview(uint128 fyTokenIn) external view returns(uint128);
function buyFYTokenPreview(uint128 fyTokenOut) external view returns(uint128);
function mint(address to, address remainder, uint256 minRatio, uint256 maxRatio) external returns (uint256, uint256, uint256);
function mintWithBase(address to, address remainder, uint256 fyTokenToBuy, uint256 minRatio, uint256 maxRatio) external returns (uint256, uint256, uint256);
function burn(address baseTo, address fyTokenTo, uint256 minRatio, uint256 maxRatio) external returns (uint256, uint256, uint256);
function burnForBase(address to, uint256 minRatio, uint256 maxRatio) external returns (uint256, uint256);
}
文件 13 的 17:Math64x64.sol
pragma solidity 0.8.6;
library Math64x64 {
int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;
int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
function fromInt (int256 x) internal pure returns (int128) {
unchecked {
require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
return int128 (x << 64);
}
}
function toInt (int128 x) internal pure returns (int64) {
unchecked {
return int64 (x >> 64);
}
}
function fromUInt (uint256 x) internal pure returns (int128) {
unchecked {
require (x <= 0x7FFFFFFFFFFFFFFF);
return int128 (int256 (x << 64));
}
}
function toUInt (int128 x) internal pure returns (uint64) {
unchecked {
require (x >= 0);
return uint64 (uint128 (x >> 64));
}
}
function from128x128 (int256 x) internal pure returns (int128) {
unchecked {
int256 result = x >> 64;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function to128x128 (int128 x) internal pure returns (int256) {
unchecked {
return int256 (x) << 64;
}
}
function add (int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) + y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function sub (int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) - y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function mul (int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) * y >> 64;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function muli (int128 x, int256 y) internal pure returns (int256) {
unchecked {
if (x == MIN_64x64) {
require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
y <= 0x1000000000000000000000000000000000000000000000000);
return -y << 63;
} else {
bool negativeResult = false;
if (x < 0) {
x = -x;
negativeResult = true;
}
if (y < 0) {
y = -y;
negativeResult = !negativeResult;
}
uint256 absoluteResult = mulu (x, uint256 (y));
if (negativeResult) {
require (absoluteResult <=
0x8000000000000000000000000000000000000000000000000000000000000000);
return -int256 (absoluteResult);
} else {
require (absoluteResult <=
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int256 (absoluteResult);
}
}
}
}
function mulu (int128 x, uint256 y) internal pure returns (uint256) {
unchecked {
if (y == 0) return 0;
require (x >= 0);
uint256 lo = (uint256 (int256 (x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
uint256 hi = uint256 (int256 (x)) * (y >> 128);
require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
hi <<= 64;
require (hi <=
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
return hi + lo;
}
}
function div (int128 x, int128 y) internal pure returns (int128) {
unchecked {
require (y != 0);
int256 result = (int256 (x) << 64) / y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function divi (int256 x, int256 y) internal pure returns (int128) {
unchecked {
require (y != 0);
bool negativeResult = false;
if (x < 0) {
x = -x;
negativeResult = true;
}
if (y < 0) {
y = -y;
negativeResult = !negativeResult;
}
uint128 absoluteResult = divuu (uint256 (x), uint256 (y));
if (negativeResult) {
require (absoluteResult <= 0x80000000000000000000000000000000);
return -int128 (absoluteResult);
} else {
require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int128 (absoluteResult);
}
}
}
function divu (uint256 x, uint256 y) internal pure returns (int128) {
unchecked {
require (y != 0);
uint128 result = divuu (x, y);
require (result <= uint128 (MAX_64x64));
return int128 (result);
}
}
function neg (int128 x) internal pure returns (int128) {
unchecked {
require (x != MIN_64x64);
return -x;
}
}
function abs (int128 x) internal pure returns (int128) {
unchecked {
require (x != MIN_64x64);
return x < 0 ? -x : x;
}
}
function inv (int128 x) internal pure returns (int128) {
unchecked {
require (x != 0);
int256 result = int256 (0x100000000000000000000000000000000) / x;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function avg (int128 x, int128 y) internal pure returns (int128) {
unchecked {
return int128 ((int256 (x) + int256 (y)) >> 1);
}
}
function gavg (int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 m = int256 (x) * int256 (y);
require (m >= 0);
require (m <
0x4000000000000000000000000000000000000000000000000000000000000000);
return int128 (sqrtu (uint256 (m)));
}
}
function pow (int128 x, uint256 y) internal pure returns (int128) {
unchecked {
bool negative = x < 0 && y & 1 == 1;
uint256 absX = uint128 (x < 0 ? -x : x);
uint256 absResult;
absResult = 0x100000000000000000000000000000000;
if (absX <= 0x10000000000000000) {
absX <<= 63;
while (y != 0) {
if (y & 0x1 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x2 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x4 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x8 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
y >>= 4;
}
absResult >>= 64;
} else {
uint256 absXShift = 63;
if (absX < 0x1000000000000000000000000) { absX <<= 32; absXShift -= 32; }
if (absX < 0x10000000000000000000000000000) { absX <<= 16; absXShift -= 16; }
if (absX < 0x1000000000000000000000000000000) { absX <<= 8; absXShift -= 8; }
if (absX < 0x10000000000000000000000000000000) { absX <<= 4; absXShift -= 4; }
if (absX < 0x40000000000000000000000000000000) { absX <<= 2; absXShift -= 2; }
if (absX < 0x80000000000000000000000000000000) { absX <<= 1; absXShift -= 1; }
uint256 resultShift = 0;
while (y != 0) {
require (absXShift < 64);
if (y & 0x1 != 0) {
absResult = absResult * absX >> 127;
resultShift += absXShift;
if (absResult > 0x100000000000000000000000000000000) {
absResult >>= 1;
resultShift += 1;
}
}
absX = absX * absX >> 127;
absXShift <<= 1;
if (absX >= 0x100000000000000000000000000000000) {
absX >>= 1;
absXShift += 1;
}
y >>= 1;
}
require (resultShift < 64);
absResult >>= 64 - resultShift;
}
int256 result = negative ? -int256 (absResult) : int256 (absResult);
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function sqrt (int128 x) internal pure returns (int128) {
unchecked {
require (x >= 0);
return int128 (sqrtu (uint256 (int256 (x)) << 64));
}
}
function log_2 (int128 x) internal pure returns (int128) {
unchecked {
require (x > 0);
int256 msb = 0;
int256 xc = x;
if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
if (xc >= 0x10000) { xc >>= 16; msb += 16; }
if (xc >= 0x100) { xc >>= 8; msb += 8; }
if (xc >= 0x10) { xc >>= 4; msb += 4; }
if (xc >= 0x4) { xc >>= 2; msb += 2; }
if (xc >= 0x2) msb += 1;
int256 result = msb - 64 << 64;
uint256 ux = uint256 (int256 (x)) << uint256 (127 - msb);
for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
ux *= ux;
uint256 b = ux >> 255;
ux >>= 127 + b;
result += bit * int256 (b);
}
return int128 (result);
}
}
function ln (int128 x) internal pure returns (int128) {
unchecked {
require (x > 0);
return int128 (int256 (
uint256 (int256 (log_2 (x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128));
}
}
function exp_2 (int128 x) internal pure returns (int128) {
unchecked {
require (x < 0x400000000000000000);
if (x < -0x400000000000000000) return 0;
uint256 result = 0x80000000000000000000000000000000;
if (x & 0x8000000000000000 > 0)
result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
if (x & 0x4000000000000000 > 0)
result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
if (x & 0x2000000000000000 > 0)
result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
if (x & 0x1000000000000000 > 0)
result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
if (x & 0x800000000000000 > 0)
result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
if (x & 0x400000000000000 > 0)
result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
if (x & 0x200000000000000 > 0)
result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
if (x & 0x100000000000000 > 0)
result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
if (x & 0x80000000000000 > 0)
result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
if (x & 0x40000000000000 > 0)
result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
if (x & 0x20000000000000 > 0)
result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
if (x & 0x10000000000000 > 0)
result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
if (x & 0x8000000000000 > 0)
result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
if (x & 0x4000000000000 > 0)
result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
if (x & 0x2000000000000 > 0)
result = result * 0x1000162E525EE054754457D5995292026 >> 128;
if (x & 0x1000000000000 > 0)
result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
if (x & 0x800000000000 > 0)
result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
if (x & 0x400000000000 > 0)
result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
if (x & 0x200000000000 > 0)
result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
if (x & 0x100000000000 > 0)
result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
if (x & 0x80000000000 > 0)
result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
if (x & 0x40000000000 > 0)
result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
if (x & 0x20000000000 > 0)
result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
if (x & 0x10000000000 > 0)
result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
if (x & 0x8000000000 > 0)
result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
if (x & 0x4000000000 > 0)
result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
if (x & 0x2000000000 > 0)
result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
if (x & 0x1000000000 > 0)
result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
if (x & 0x800000000 > 0)
result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
if (x & 0x400000000 > 0)
result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
if (x & 0x200000000 > 0)
result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
if (x & 0x100000000 > 0)
result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
if (x & 0x80000000 > 0)
result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
if (x & 0x40000000 > 0)
result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
if (x & 0x20000000 > 0)
result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
if (x & 0x10000000 > 0)
result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
if (x & 0x8000000 > 0)
result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
if (x & 0x4000000 > 0)
result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
if (x & 0x2000000 > 0)
result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
if (x & 0x1000000 > 0)
result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
if (x & 0x800000 > 0)
result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
if (x & 0x400000 > 0)
result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
if (x & 0x200000 > 0)
result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
if (x & 0x100000 > 0)
result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
if (x & 0x80000 > 0)
result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
if (x & 0x40000 > 0)
result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
if (x & 0x20000 > 0)
result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
if (x & 0x10000 > 0)
result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
if (x & 0x8000 > 0)
result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
if (x & 0x4000 > 0)
result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
if (x & 0x2000 > 0)
result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
if (x & 0x1000 > 0)
result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
if (x & 0x800 > 0)
result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
if (x & 0x400 > 0)
result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
if (x & 0x200 > 0)
result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
if (x & 0x100 > 0)
result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
if (x & 0x80 > 0)
result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
if (x & 0x40 > 0)
result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
if (x & 0x20 > 0)
result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
if (x & 0x10 > 0)
result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
if (x & 0x8 > 0)
result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
if (x & 0x4 > 0)
result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
if (x & 0x2 > 0)
result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
if (x & 0x1 > 0)
result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;
result >>= uint256 (int256 (63 - (x >> 64)));
require (result <= uint256 (int256 (MAX_64x64)));
return int128 (int256 (result));
}
}
function exp (int128 x) internal pure returns (int128) {
unchecked {
require (x < 0x400000000000000000);
if (x < -0x400000000000000000) return 0;
return exp_2 (
int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
}
}
function divuu (uint256 x, uint256 y) private pure returns (uint128) {
unchecked {
require (y != 0);
uint256 result;
if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
result = (x << 64) / y;
else {
uint256 msb = 192;
uint256 xc = x >> 192;
if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
if (xc >= 0x10000) { xc >>= 16; msb += 16; }
if (xc >= 0x100) { xc >>= 8; msb += 8; }
if (xc >= 0x10) { xc >>= 4; msb += 4; }
if (xc >= 0x4) { xc >>= 2; msb += 2; }
if (xc >= 0x2) msb += 1;
result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 hi = result * (y >> 128);
uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 xh = x >> 192;
uint256 xl = x << 64;
if (xl < lo) xh -= 1;
xl -= lo;
lo = hi << 128;
if (xl < lo) xh -= 1;
xl -= lo;
assert (xh == hi >> 128);
result += xl / y;
}
require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return uint128 (result);
}
}
function sqrtu (uint256 x) private pure returns (uint128) {
unchecked {
if (x == 0) return 0;
else {
uint256 xx = x;
uint256 r = 1;
if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; }
if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; }
if (xx >= 0x100000000) { xx >>= 32; r <<= 16; }
if (xx >= 0x10000) { xx >>= 16; r <<= 8; }
if (xx >= 0x100) { xx >>= 8; r <<= 4; }
if (xx >= 0x10) { xx >>= 4; r <<= 2; }
if (xx >= 0x8) { r <<= 1; }
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
uint256 r1 = x / r;
return uint128 (r < r1 ? r : r1);
}
}
}
}
文件 14 的 17:MinimalTransferHelper.sol
pragma solidity >=0.6.0;
import "./IERC20.sol";
import "../utils/RevertMsgExtractor.sol";
library MinimalTransferHelper {
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
if (!(success && (data.length == 0 || abi.decode(data, (bool))))) revert(RevertMsgExtractor.getRevertMsg(data));
}
}
文件 15 的 17:Pool.sol
pragma solidity 0.8.6;
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";
import "@yield-protocol/utils-v2/contracts/token/IERC20Metadata.sol";
import "@yield-protocol/utils-v2/contracts/token/ERC20Permit.sol";
import "@yield-protocol/utils-v2/contracts/token/MinimalTransferHelper.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU256U128.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU256U112.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU256I256.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU128U112.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU128I128.sol";
import "@yield-protocol/yieldspace-interfaces/IPool.sol";
import "@yield-protocol/vault-interfaces/IFYToken.sol";
import "./YieldMath.sol";
contract Pool is IPool, ERC20Permit {
using CastU256U128 for uint256;
using CastU256U112 for uint256;
using CastU256I256 for uint256;
using CastU128U112 for uint128;
using CastU128I128 for uint128;
using MinimalTransferHelper for IERC20;
event Trade(uint32 maturity, address indexed from, address indexed to, int256 bases, int256 fyTokens);
event Liquidity(uint32 maturity, address indexed from, address indexed to, address indexed fyTokenTo, int256 bases, int256 fyTokens, int256 poolTokens);
event Sync(uint112 baseCached, uint112 fyTokenCached, uint256 cumulativeBalancesRatio);
int128 public immutable override ts;
int128 public immutable override g1;
int128 public immutable override g2;
uint32 public immutable override maturity;
uint96 public immutable override scaleFactor;
IERC20 public immutable override base;
IFYToken public immutable override fyToken;
uint112 private baseCached;
uint112 private fyTokenCached;
uint32 private blockTimestampLast;
uint256 public cumulativeBalancesRatio;
constructor(IERC20 base_, IFYToken fyToken_, int128 ts_, int128 g1_, int128 g2_)
ERC20Permit(
string(abi.encodePacked(IERC20Metadata(address(fyToken_)).name(), " LP")),
string(abi.encodePacked(IERC20Metadata(address(fyToken_)).symbol(), "LP")),
IERC20Metadata(address(fyToken_)).decimals()
)
{
fyToken = fyToken_;
base = base_;
uint256 maturity_ = fyToken_.maturity();
require (maturity_ <= type(uint32).max, "Pool: Maturity too far in the future");
maturity = uint32(maturity_);
ts = ts_;
g1 = g1_;
g2 = g2_;
scaleFactor = uint96(10 ** (18 - uint96(decimals)));
}
modifier beforeMaturity() {
require(
block.timestamp < maturity,
"Pool: Too late"
);
_;
}
function sync() external {
_update(_getBaseBalance(), _getFYTokenBalance(), baseCached, fyTokenCached);
}
function getCache()
external view override
returns (uint112, uint112, uint32)
{
return (baseCached, fyTokenCached, blockTimestampLast);
}
function getFYTokenBalance()
public view override
returns(uint112)
{
return _getFYTokenBalance();
}
function getBaseBalance()
public view override
returns(uint112)
{
return _getBaseBalance();
}
function _getFYTokenBalance()
internal view
returns(uint112)
{
return (fyToken.balanceOf(address(this)) + _totalSupply).u112();
}
function _getBaseBalance()
internal view
returns(uint112)
{
return base.balanceOf(address(this)).u112();
}
function retrieveBase(address to)
external override
returns(uint128 retrieved)
{
retrieved = _getBaseBalance() - baseCached;
base.safeTransfer(to, retrieved);
}
function retrieveFYToken(address to)
external override
returns(uint128 retrieved)
{
retrieved = _getFYTokenBalance() - fyTokenCached;
IERC20(address(fyToken)).safeTransfer(to, retrieved);
}
function _update(uint128 baseBalance, uint128 fyBalance, uint112 _baseCached, uint112 _fyTokenCached) private {
uint32 blockTimestamp = uint32(block.timestamp);
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
if (timeElapsed > 0 && _baseCached != 0 && _fyTokenCached != 0) {
uint256 scaledFYTokenCached = uint256(_fyTokenCached) * 1e27;
cumulativeBalancesRatio += scaledFYTokenCached * timeElapsed / _baseCached;
}
baseCached = baseBalance.u112();
fyTokenCached = fyBalance.u112();
blockTimestampLast = blockTimestamp;
emit Sync(baseCached, fyTokenCached, cumulativeBalancesRatio);
}
function mint(address to, address remainder, uint256 minRatio, uint256 maxRatio)
external override
returns (uint256, uint256, uint256)
{
return _mintInternal(to, remainder, 0, minRatio, maxRatio);
}
function mintWithBase(address to, address remainder, uint256 fyTokenToBuy, uint256 minRatio, uint256 maxRatio)
external override
returns (uint256, uint256, uint256)
{
return _mintInternal(to, remainder, fyTokenToBuy, minRatio, maxRatio);
}
function _mintInternal(address to, address remainder, uint256 fyTokenToBuy, uint256 minRatio, uint256 maxRatio)
internal
returns (uint256 baseIn, uint256 fyTokenIn, uint256 tokensMinted)
{
uint256 supply = _totalSupply;
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
uint256 _realFYTokenCached = _fyTokenCached - supply;
uint256 baseBalance = base.balanceOf(address(this));
uint256 fyTokenBalance = fyToken.balanceOf(address(this));
uint256 baseAvailable = baseBalance - _baseCached;
require (
_realFYTokenCached == 0 || (
uint256(_baseCached) * 1e18 / _realFYTokenCached >= minRatio &&
uint256(_baseCached) * 1e18 / _realFYTokenCached <= maxRatio
),
"Pool: Reserves ratio changed"
);
if (supply == 0) {
baseIn = baseAvailable;
tokensMinted = baseIn;
} else if (_realFYTokenCached == 0) {
baseIn = baseAvailable;
tokensMinted = supply * baseIn / _baseCached;
} else {
uint256 baseToSell;
if (fyTokenToBuy > 0) {
baseToSell = _buyFYTokenPreview(
fyTokenToBuy.u128(),
_baseCached,
_fyTokenCached
);
}
fyTokenIn = fyTokenBalance - _realFYTokenCached;
tokensMinted = (supply * (fyTokenToBuy + fyTokenIn)) / (_realFYTokenCached - fyTokenToBuy);
baseIn = baseToSell + ((_baseCached + baseToSell) * tokensMinted) / supply;
require(baseAvailable >= baseIn, "Pool: Not enough base token in");
}
_update(
(_baseCached + baseIn).u128(),
(_fyTokenCached + fyTokenIn + tokensMinted).u128(),
_baseCached,
_fyTokenCached
);
_mint(to, tokensMinted);
if (baseAvailable - baseIn > 0) base.safeTransfer(remainder, baseAvailable - baseIn);
emit Liquidity(maturity, msg.sender, to, address(0), -(baseIn.i256()), -(fyTokenIn.i256()), tokensMinted.i256());
}
function burn(address baseTo, address fyTokenTo, uint256 minRatio, uint256 maxRatio)
external override
returns (uint256, uint256, uint256)
{
return _burnInternal(baseTo, fyTokenTo, false, minRatio, maxRatio);
}
function burnForBase(address to, uint256 minRatio, uint256 maxRatio)
external override
returns (uint256 tokensBurned, uint256 baseOut)
{
(tokensBurned, baseOut, ) = _burnInternal(to, address(0), true, minRatio, maxRatio);
}
function _burnInternal(address baseTo, address fyTokenTo, bool tradeToBase, uint256 minRatio, uint256 maxRatio)
internal
returns (uint256 tokensBurned, uint256 tokenOut, uint256 fyTokenOut)
{
tokensBurned = _balanceOf[address(this)];
uint256 supply = _totalSupply;
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
uint256 _realFYTokenCached = _fyTokenCached - supply;
require (
_realFYTokenCached == 0 || (
uint256(_baseCached) * 1e18 / _realFYTokenCached >= minRatio &&
uint256(_baseCached) * 1e18 / _realFYTokenCached <= maxRatio
),
"Pool: Reserves ratio changed"
);
tokenOut = (tokensBurned * _baseCached) / supply;
fyTokenOut = (tokensBurned * _realFYTokenCached) / supply;
if (tradeToBase) {
tokenOut += YieldMath.baseOutForFYTokenIn(
(_baseCached - tokenOut.u128()) * scaleFactor,
(_fyTokenCached - fyTokenOut.u128()) * scaleFactor,
fyTokenOut.u128() * scaleFactor,
maturity - uint32(block.timestamp),
ts,
g2
) / scaleFactor;
fyTokenOut = 0;
}
_update(
(_baseCached - tokenOut).u128(),
(_fyTokenCached - fyTokenOut - tokensBurned).u128(),
_baseCached,
_fyTokenCached
);
_burn(address(this), tokensBurned);
base.safeTransfer(baseTo, tokenOut);
if (fyTokenOut > 0) IERC20(address(fyToken)).safeTransfer(fyTokenTo, fyTokenOut);
emit Liquidity(maturity, msg.sender, baseTo, fyTokenTo, tokenOut.i256(), fyTokenOut.i256(), -(tokensBurned.i256()));
}
function sellBase(address to, uint128 min)
external override
returns(uint128)
{
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
uint112 _baseBalance = _getBaseBalance();
uint112 _fyTokenBalance = _getFYTokenBalance();
uint128 baseIn = _baseBalance - _baseCached;
uint128 fyTokenOut = _sellBasePreview(
baseIn,
_baseCached,
_fyTokenBalance
);
require(
fyTokenOut >= min,
"Pool: Not enough fyToken obtained"
);
_update(
_baseBalance,
_fyTokenBalance - fyTokenOut,
_baseCached,
_fyTokenCached
);
IERC20(address(fyToken)).safeTransfer(to, fyTokenOut);
emit Trade(maturity, msg.sender, to, -(baseIn.i128()), fyTokenOut.i128());
return fyTokenOut;
}
function sellBasePreview(uint128 baseIn)
external view override
returns(uint128)
{
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
return _sellBasePreview(baseIn, _baseCached, _fyTokenCached);
}
function _sellBasePreview(
uint128 baseIn,
uint112 baseBalance,
uint112 fyTokenBalance
)
private view
beforeMaturity
returns(uint128)
{
uint128 fyTokenOut = YieldMath.fyTokenOutForBaseIn(
baseBalance * scaleFactor,
fyTokenBalance * scaleFactor,
baseIn * scaleFactor,
maturity - uint32(block.timestamp),
ts,
g1
) / scaleFactor;
require(
fyTokenBalance - fyTokenOut >= baseBalance + baseIn,
"Pool: fyToken balance too low"
);
return fyTokenOut;
}
function buyBase(address to, uint128 tokenOut, uint128 max)
external override
returns(uint128)
{
uint128 fyTokenBalance = _getFYTokenBalance();
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
uint128 fyTokenIn = _buyBasePreview(
tokenOut,
_baseCached,
_fyTokenCached
);
require(
fyTokenBalance - _fyTokenCached >= fyTokenIn,
"Pool: Not enough fyToken in"
);
require(
fyTokenIn <= max,
"Pool: Too much fyToken in"
);
_update(
_baseCached - tokenOut,
_fyTokenCached + fyTokenIn,
_baseCached,
_fyTokenCached
);
base.safeTransfer(to, tokenOut);
emit Trade(maturity, msg.sender, to, tokenOut.i128(), -(fyTokenIn.i128()));
return fyTokenIn;
}
function buyBasePreview(uint128 tokenOut)
external view override
returns(uint128)
{
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
return _buyBasePreview(tokenOut, _baseCached, _fyTokenCached);
}
function _buyBasePreview(
uint128 tokenOut,
uint112 baseBalance,
uint112 fyTokenBalance
)
private view
beforeMaturity
returns(uint128)
{
return YieldMath.fyTokenInForBaseOut(
baseBalance * scaleFactor,
fyTokenBalance * scaleFactor,
tokenOut * scaleFactor,
maturity - uint32(block.timestamp),
ts,
g2
) / scaleFactor;
}
function sellFYToken(address to, uint128 min)
external override
returns(uint128)
{
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
uint112 _fyTokenBalance = _getFYTokenBalance();
uint112 _baseBalance = _getBaseBalance();
uint128 fyTokenIn = _fyTokenBalance - _fyTokenCached;
uint128 baseOut = _sellFYTokenPreview(
fyTokenIn,
_baseCached,
_fyTokenCached
);
require(
baseOut >= min,
"Pool: Not enough base obtained"
);
_update(
_baseBalance - baseOut,
_fyTokenBalance,
_baseCached,
_fyTokenCached
);
base.safeTransfer(to, baseOut);
emit Trade(maturity, msg.sender, to, baseOut.i128(), -(fyTokenIn.i128()));
return baseOut;
}
function sellFYTokenPreview(uint128 fyTokenIn)
external view override
returns(uint128)
{
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
return _sellFYTokenPreview(fyTokenIn, _baseCached, _fyTokenCached);
}
function _sellFYTokenPreview(
uint128 fyTokenIn,
uint112 baseBalance,
uint112 fyTokenBalance
)
private view
beforeMaturity
returns(uint128)
{
return YieldMath.baseOutForFYTokenIn(
baseBalance * scaleFactor,
fyTokenBalance * scaleFactor,
fyTokenIn * scaleFactor,
maturity - uint32(block.timestamp),
ts,
g2
) / scaleFactor;
}
function buyFYToken(address to, uint128 fyTokenOut, uint128 max)
external override
returns(uint128)
{
uint128 baseBalance = _getBaseBalance();
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
uint128 baseIn = _buyFYTokenPreview(
fyTokenOut,
_baseCached,
_fyTokenCached
);
require(
baseBalance - _baseCached >= baseIn,
"Pool: Not enough base token in"
);
require(
baseIn <= max,
"Pool: Too much base token in"
);
_update(
_baseCached + baseIn,
_fyTokenCached - fyTokenOut,
_baseCached,
_fyTokenCached
);
IERC20(address(fyToken)).safeTransfer(to, fyTokenOut);
emit Trade(maturity, msg.sender, to, -(baseIn.i128()), fyTokenOut.i128());
return baseIn;
}
function buyFYTokenPreview(uint128 fyTokenOut)
external view override
returns(uint128)
{
(uint112 _baseCached, uint112 _fyTokenCached) =
(baseCached, fyTokenCached);
return _buyFYTokenPreview(fyTokenOut, _baseCached, _fyTokenCached);
}
function _buyFYTokenPreview(
uint128 fyTokenOut,
uint128 baseBalance,
uint128 fyTokenBalance
)
private view
beforeMaturity
returns(uint128)
{
uint128 baseIn = YieldMath.baseInForFYTokenOut(
baseBalance * scaleFactor,
fyTokenBalance * scaleFactor,
fyTokenOut * scaleFactor,
maturity - uint32(block.timestamp),
ts,
g1
) / scaleFactor;
require(
fyTokenBalance - fyTokenOut >= baseBalance + baseIn,
"Pool: fyToken balance too low"
);
return baseIn;
}
}
文件 16 的 17:RevertMsgExtractor.sol
pragma solidity >=0.6.0;
library RevertMsgExtractor {
function getRevertMsg(bytes memory returnData)
internal pure
returns (string memory)
{
if (returnData.length < 68) return "Transaction reverted silently";
assembly {
returnData := add(returnData, 0x04)
}
return abi.decode(returnData, (string));
}
}
文件 17 的 17:YieldMath.sol
pragma solidity 0.8.6;
import "./Math64x64.sol";
library Exp64x64 {
function pow(uint128 x, uint128 y, uint128 z)
internal pure returns(uint128) {
unchecked {
require(z != 0);
if(x == 0) {
require(y != 0);
return 0;
} else {
uint256 l =
uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - log_2(x)) * y / z;
if(l > 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) return 0;
else return pow_2(uint128(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - l));
}
}
}
function log_2(uint128 x)
internal pure returns(uint128) {
unchecked {
require(x != 0);
uint b = x;
uint l = 0xFE000000000000000000000000000000;
if(b < 0x10000000000000000) {l -= 0x80000000000000000000000000000000; b <<= 64;}
if(b < 0x1000000000000000000000000) {l -= 0x40000000000000000000000000000000; b <<= 32;}
if(b < 0x10000000000000000000000000000) {l -= 0x20000000000000000000000000000000; b <<= 16;}
if(b < 0x1000000000000000000000000000000) {l -= 0x10000000000000000000000000000000; b <<= 8;}
if(b < 0x10000000000000000000000000000000) {l -= 0x8000000000000000000000000000000; b <<= 4;}
if(b < 0x40000000000000000000000000000000) {l -= 0x4000000000000000000000000000000; b <<= 2;}
if(b < 0x80000000000000000000000000000000) {l -= 0x2000000000000000000000000000000; b <<= 1;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000000;}
b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000000;}
return uint128(l);
}
}
function pow_2(uint128 x)
internal pure returns(uint128) {
unchecked {
uint r = 0x80000000000000000000000000000000;
if(x & 0x1000000000000000000000000000000 > 0) r = r * 0xb504f333f9de6484597d89b3754abe9f >> 127;
if(x & 0x800000000000000000000000000000 > 0) r = r * 0x9837f0518db8a96f46ad23182e42f6f6 >> 127;
if(x & 0x400000000000000000000000000000 > 0) r = r * 0x8b95c1e3ea8bd6e6fbe4628758a53c90 >> 127;
if(x & 0x200000000000000000000000000000 > 0) r = r * 0x85aac367cc487b14c5c95b8c2154c1b2 >> 127;
if(x & 0x100000000000000000000000000000 > 0) r = r * 0x82cd8698ac2ba1d73e2a475b46520bff >> 127;
if(x & 0x80000000000000000000000000000 > 0) r = r * 0x8164d1f3bc0307737be56527bd14def4 >> 127;
if(x & 0x40000000000000000000000000000 > 0) r = r * 0x80b1ed4fd999ab6c25335719b6e6fd20 >> 127;
if(x & 0x20000000000000000000000000000 > 0) r = r * 0x8058d7d2d5e5f6b094d589f608ee4aa2 >> 127;
if(x & 0x10000000000000000000000000000 > 0) r = r * 0x802c6436d0e04f50ff8ce94a6797b3ce >> 127;
if(x & 0x8000000000000000000000000000 > 0) r = r * 0x8016302f174676283690dfe44d11d008 >> 127;
if(x & 0x4000000000000000000000000000 > 0) r = r * 0x800b179c82028fd0945e54e2ae18f2f0 >> 127;
if(x & 0x2000000000000000000000000000 > 0) r = r * 0x80058baf7fee3b5d1c718b38e549cb93 >> 127;
if(x & 0x1000000000000000000000000000 > 0) r = r * 0x8002c5d00fdcfcb6b6566a58c048be1f >> 127;
if(x & 0x800000000000000000000000000 > 0) r = r * 0x800162e61bed4a48e84c2e1a463473d9 >> 127;
if(x & 0x400000000000000000000000000 > 0) r = r * 0x8000b17292f702a3aa22beacca949013 >> 127;
if(x & 0x200000000000000000000000000 > 0) r = r * 0x800058b92abbae02030c5fa5256f41fe >> 127;
if(x & 0x100000000000000000000000000 > 0) r = r * 0x80002c5c8dade4d71776c0f4dbea67d6 >> 127;
if(x & 0x80000000000000000000000000 > 0) r = r * 0x8000162e44eaf636526be456600bdbe4 >> 127;
if(x & 0x40000000000000000000000000 > 0) r = r * 0x80000b1721fa7c188307016c1cd4e8b6 >> 127;
if(x & 0x20000000000000000000000000 > 0) r = r * 0x8000058b90de7e4cecfc487503488bb1 >> 127;
if(x & 0x10000000000000000000000000 > 0) r = r * 0x800002c5c8678f36cbfce50a6de60b14 >> 127;
if(x & 0x8000000000000000000000000 > 0) r = r * 0x80000162e431db9f80b2347b5d62e516 >> 127;
if(x & 0x4000000000000000000000000 > 0) r = r * 0x800000b1721872d0c7b08cf1e0114152 >> 127;
if(x & 0x2000000000000000000000000 > 0) r = r * 0x80000058b90c1aa8a5c3736cb77e8dff >> 127;
if(x & 0x1000000000000000000000000 > 0) r = r * 0x8000002c5c8605a4635f2efc2362d978 >> 127;
if(x & 0x800000000000000000000000 > 0) r = r * 0x800000162e4300e635cf4a109e3939bd >> 127;
if(x & 0x400000000000000000000000 > 0) r = r * 0x8000000b17217ff81bef9c551590cf83 >> 127;
if(x & 0x200000000000000000000000 > 0) r = r * 0x800000058b90bfdd4e39cd52c0cfa27c >> 127;
if(x & 0x100000000000000000000000 > 0) r = r * 0x80000002c5c85fe6f72d669e0e76e411 >> 127;
if(x & 0x80000000000000000000000 > 0) r = r * 0x8000000162e42ff18f9ad35186d0df28 >> 127;
if(x & 0x40000000000000000000000 > 0) r = r * 0x80000000b17217f84cce71aa0dcfffe7 >> 127;
if(x & 0x20000000000000000000000 > 0) r = r * 0x8000000058b90bfc07a77ad56ed22aaa >> 127;
if(x & 0x10000000000000000000000 > 0) r = r * 0x800000002c5c85fdfc23cdead40da8d6 >> 127;
if(x & 0x8000000000000000000000 > 0) r = r * 0x80000000162e42fefc25eb1571853a66 >> 127;
if(x & 0x4000000000000000000000 > 0) r = r * 0x800000000b17217f7d97f692baacded5 >> 127;
if(x & 0x2000000000000000000000 > 0) r = r * 0x80000000058b90bfbead3b8b5dd254d7 >> 127;
if(x & 0x1000000000000000000000 > 0) r = r * 0x8000000002c5c85fdf4eedd62f084e67 >> 127;
if(x & 0x800000000000000000000 > 0) r = r * 0x800000000162e42fefa58aef378bf586 >> 127;
if(x & 0x400000000000000000000 > 0) r = r * 0x8000000000b17217f7d24a78a3c7ef02 >> 127;
if(x & 0x200000000000000000000 > 0) r = r * 0x800000000058b90bfbe9067c93e474a6 >> 127;
if(x & 0x100000000000000000000 > 0) r = r * 0x80000000002c5c85fdf47b8e5a72599f >> 127;
if(x & 0x80000000000000000000 > 0) r = r * 0x8000000000162e42fefa3bdb315934a2 >> 127;
if(x & 0x40000000000000000000 > 0) r = r * 0x80000000000b17217f7d1d7299b49c46 >> 127;
if(x & 0x20000000000000000000 > 0) r = r * 0x8000000000058b90bfbe8e9a8d1c4ea0 >> 127;
if(x & 0x10000000000000000000 > 0) r = r * 0x800000000002c5c85fdf4745969ea76f >> 127;
if(x & 0x8000000000000000000 > 0) r = r * 0x80000000000162e42fefa3a0df5373bf >> 127;
if(x & 0x4000000000000000000 > 0) r = r * 0x800000000000b17217f7d1cff4aac1e1 >> 127;
if(x & 0x2000000000000000000 > 0) r = r * 0x80000000000058b90bfbe8e7db95a2f1 >> 127;
if(x & 0x1000000000000000000 > 0) r = r * 0x8000000000002c5c85fdf473e61ae1f8 >> 127;
if(x & 0x800000000000000000 > 0) r = r * 0x800000000000162e42fefa39f121751c >> 127;
if(x & 0x400000000000000000 > 0) r = r * 0x8000000000000b17217f7d1cf815bb96 >> 127;
if(x & 0x200000000000000000 > 0) r = r * 0x800000000000058b90bfbe8e7bec1e0d >> 127;
if(x & 0x100000000000000000 > 0) r = r * 0x80000000000002c5c85fdf473dee5f17 >> 127;
if(x & 0x80000000000000000 > 0) r = r * 0x8000000000000162e42fefa39ef5438f >> 127;
if(x & 0x40000000000000000 > 0) r = r * 0x80000000000000b17217f7d1cf7a26c8 >> 127;
if(x & 0x20000000000000000 > 0) r = r * 0x8000000000000058b90bfbe8e7bcf4a4 >> 127;
if(x & 0x10000000000000000 > 0) r = r * 0x800000000000002c5c85fdf473de72a2 >> 127;
r >>= 127 -(x >> 121);
return uint128(r);
}
}
}
library YieldMath {
using Math64x64 for int128;
using Math64x64 for uint128;
using Math64x64 for int256;
using Math64x64 for uint256;
using Exp64x64 for uint128;
uint128 public constant ONE = 0x10000000000000000;
uint128 public constant TWO = 0x20000000000000000;
uint256 public constant MAX = type(uint128).max;
uint256 public constant VAR = 1e12;
function invariant(uint128 baseReserves, uint128 fyTokenReserves, uint256 totalSupply, uint128 timeTillMaturity, int128 ts)
public pure returns(uint128)
{
if (totalSupply == 0) return 0;
unchecked {
int128 a = int128(ONE).sub(ts.mul(timeTillMaturity.fromUInt()));
require (a > 0, "YieldMath: Too far from maturity");
uint256 sum =
uint256(baseReserves.pow(uint128 (a), ONE)) +
uint256(fyTokenReserves.pow(uint128 (a), ONE)) >> 1;
require(sum < MAX, "YieldMath: Sum overflow");
uint256 result = uint256(uint128(sum).pow(ONE, uint128(a))) * 1e18 / totalSupply;
require (result < MAX, "YieldMath: Result overflow");
return uint128(result);
}
}
function fyTokenOutForBaseIn(
uint128 baseReserves, uint128 fyTokenReserves, uint128 baseAmount,
uint128 timeTillMaturity, int128 ts, int128 g)
public pure returns(uint128) {
unchecked {
uint128 a = _computeA(timeTillMaturity, ts, g);
uint256 za = baseReserves.pow(a, ONE);
uint256 ya = fyTokenReserves.pow(a, ONE);
uint256 zx = uint256(baseReserves) + uint256(baseAmount);
require(zx <= MAX, "YieldMath: Too much base in");
uint256 zxa = uint128(zx).pow(a, ONE);
uint256 sum = za + ya - zxa;
require(sum <= MAX, "YieldMath: Insufficient fyToken reserves");
uint256 result = uint256(fyTokenReserves) - uint256(uint128(sum).pow(ONE, a));
require(result <= MAX, "YieldMath: Rounding induced error");
result = result > VAR ? result - VAR : 0;
return uint128(result);
}
}
function baseOutForFYTokenIn(
uint128 baseReserves, uint128 fyTokenReserves, uint128 fyTokenAmount,
uint128 timeTillMaturity, int128 ts, int128 g)
public pure returns(uint128) {
unchecked {
uint128 a = _computeA(timeTillMaturity, ts, g);
uint256 za = baseReserves.pow(a, ONE);
uint256 ya = fyTokenReserves.pow(a, ONE);
uint256 yx = uint256(fyTokenReserves) + uint256(fyTokenAmount);
require(yx <= MAX, "YieldMath: Too much fyToken in");
uint256 yxa = uint128(yx).pow(a, ONE);
uint256 sum = za + ya - yxa;
require(sum <= MAX, "YieldMath: Insufficient base reserves");
uint256 result = uint256(baseReserves) - uint256(uint128(sum).pow(ONE, a));
require(result <= MAX, "YieldMath: Rounding induced error");
result = result > VAR ? result - VAR : 0;
return uint128(result);
}
}
function fyTokenInForBaseOut(
uint128 baseReserves, uint128 fyTokenReserves, uint128 baseAmount,
uint128 timeTillMaturity, int128 ts, int128 g)
public pure returns(uint128) {
unchecked {
uint128 a = _computeA(timeTillMaturity, ts, g);
uint256 za = baseReserves.pow(a, ONE);
uint256 ya = fyTokenReserves.pow(a, ONE);
uint256 zx = uint256(baseReserves) - uint256(baseAmount);
require(zx <= MAX, "YieldMath: Too much base out");
uint256 zxa = uint128(zx).pow(a, ONE);
uint256 sum = za + ya - zxa;
require(sum <= MAX, "YieldMath: Resulting fyToken reserves too high");
uint256 result = uint256(uint128(sum).pow(ONE, a)) - uint256(fyTokenReserves);
require(result <= MAX, "YieldMath: Rounding induced error");
result = result < MAX - VAR ? result + VAR : MAX;
return uint128(result);
}
}
function baseInForFYTokenOut(
uint128 baseReserves, uint128 fyTokenReserves, uint128 fyTokenAmount,
uint128 timeTillMaturity, int128 ts, int128 g)
public pure returns(uint128) {
unchecked {
uint128 a = _computeA(timeTillMaturity, ts, g);
uint256 za = baseReserves.pow(a, ONE);
uint256 ya = fyTokenReserves.pow(a, ONE);
uint256 yx = uint256(fyTokenReserves) - uint256(fyTokenAmount);
require(yx <= MAX, "YieldMath: Too much fyToken out");
uint256 yxa = uint128(yx).pow(a, ONE);
uint256 sum = za + ya - yxa;
require(sum <= MAX, "YieldMath: Resulting base reserves too high");
uint256 result = uint256(uint128(sum).pow(ONE, a)) - uint256(baseReserves);
require(result <= MAX, "YieldMath: Rounding induced error");
result = result < MAX - VAR ? result + VAR : MAX;
return uint128(result);
}
}
function maxFYTokenOut(
uint128 baseReserves, uint128 fyTokenReserves,
uint128 timeTillMaturity, int128 ts, int128 g)
public pure returns(uint128) {
if (baseReserves == fyTokenReserves) return 0;
unchecked {
uint128 a = _computeA(timeTillMaturity, ts, g);
uint128 xa = baseReserves.pow(a, ONE);
uint128 ya = fyTokenReserves.pow(a, ONE);
int128 xy2 = (xa + ya).divu(TWO);
uint inaccessible = uint256(uint128(xy2).pow(ONE, a));
require(inaccessible <= MAX, "YieldMath: Rounding induced error");
inaccessible = inaccessible < MAX - VAR ? inaccessible + VAR : MAX;
return uint128(inaccessible) > fyTokenReserves ? 0 : fyTokenReserves - uint128(inaccessible);
}
}
function maxFYTokenIn(
uint128 baseReserves, uint128 fyTokenReserves,
uint128 timeTillMaturity, int128 ts, int128 g)
public pure returns(uint128) {
unchecked {
uint128 b = _computeB(timeTillMaturity, ts, g);
uint128 xa = baseReserves.pow(b, ONE);
uint128 ya = fyTokenReserves.pow(b, ONE);
uint result = (xa + ya).pow(ONE, b) - fyTokenReserves;
require(result <= MAX, "YieldMath: Rounding induced error");
result = result > VAR ? result - VAR : 0;
return uint128(result);
}
}
function maxBaseIn(
uint128 baseReserves, uint128 fyTokenReserves,
uint128 timeTillMaturity, int128 ts, int128 g)
public pure returns (uint128) {
uint128 _maxFYTokenOut = maxFYTokenOut(baseReserves, fyTokenReserves, timeTillMaturity, ts, g);
if (_maxFYTokenOut > 0)
return baseInForFYTokenOut(baseReserves, fyTokenReserves, _maxFYTokenOut, timeTillMaturity, ts, g);
return 0;
}
function maxBaseOut(
uint128 baseReserves, uint128 fyTokenReserves,
uint128 timeTillMaturity, int128 ts, int128 g)
public pure returns (uint128) {
uint128 _maxFYTokenIn = maxFYTokenIn(baseReserves, fyTokenReserves, timeTillMaturity, ts, g);
return baseOutForFYTokenIn(baseReserves, fyTokenReserves, _maxFYTokenIn, timeTillMaturity, ts, g);
}
function _computeA(uint128 timeTillMaturity, int128 ts, int128 g) private pure returns (uint128) {
unchecked {
int128 t = ts.mul(timeTillMaturity.fromUInt());
require(t >= 0, "YieldMath: t must be positive");
int128 a = int128(ONE).sub(g.mul(t));
require(a > 0, "YieldMath: Too far from maturity");
require(a <= int128(ONE), "YieldMath: g must be positive");
return uint128(a);
}
}
function _computeB(uint128 timeTillMaturity, int128 ts, int128 g) private pure returns (uint128) {
unchecked {
int128 t = ts.mul(timeTillMaturity.fromUInt());
require(t >= 0, "YieldMath: t must be positive");
int128 b = int128(ONE).sub(t.div(g));
require(b > 0, "YieldMath: Too far from maturity");
require(b <= int128(ONE), "YieldMath: g must be positive");
return uint128(b);
}
}
}
{
"compilationTarget": {
"@yield-protocol/yieldspace-v2/contracts/Pool.sol": "Pool"
},
"evmVersion": "berlin",
"libraries": {
"@yield-protocol/yieldspace-v2/contracts/YieldMath.sol:YieldMath": "0x50c15883934c1a14bfc07904afd383f7fb80b354"
},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"base_","type":"address"},{"internalType":"contract IFYToken","name":"fyToken_","type":"address"},{"internalType":"int128","name":"ts_","type":"int128"},{"internalType":"int128","name":"g1_","type":"int128"},{"internalType":"int128","name":"g2_","type":"int128"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"maturity","type":"uint32"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"fyTokenTo","type":"address"},{"indexed":false,"internalType":"int256","name":"bases","type":"int256"},{"indexed":false,"internalType":"int256","name":"fyTokens","type":"int256"},{"indexed":false,"internalType":"int256","name":"poolTokens","type":"int256"}],"name":"Liquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint112","name":"baseCached","type":"uint112"},{"indexed":false,"internalType":"uint112","name":"fyTokenCached","type":"uint112"},{"indexed":false,"internalType":"uint256","name":"cumulativeBalancesRatio","type":"uint256"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"maturity","type":"uint32"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"int256","name":"bases","type":"int256"},{"indexed":false,"internalType":"int256","name":"fyTokens","type":"int256"}],"name":"Trade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"base","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseTo","type":"address"},{"internalType":"address","name":"fyTokenTo","type":"address"},{"internalType":"uint256","name":"minRatio","type":"uint256"},{"internalType":"uint256","name":"maxRatio","type":"uint256"}],"name":"burn","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minRatio","type":"uint256"},{"internalType":"uint256","name":"maxRatio","type":"uint256"}],"name":"burnForBase","outputs":[{"internalType":"uint256","name":"tokensBurned","type":"uint256"},{"internalType":"uint256","name":"baseOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"tokenOut","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"name":"buyBase","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"tokenOut","type":"uint128"}],"name":"buyBasePreview","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"fyTokenOut","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"name":"buyFYToken","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"fyTokenOut","type":"uint128"}],"name":"buyFYTokenPreview","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cumulativeBalancesRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deploymentChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fyToken","outputs":[{"internalType":"contract IFYToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"g1","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"g2","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseBalance","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCache","outputs":[{"internalType":"uint112","name":"","type":"uint112"},{"internalType":"uint112","name":"","type":"uint112"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFYTokenBalance","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maturity","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"remainder","type":"address"},{"internalType":"uint256","name":"minRatio","type":"uint256"},{"internalType":"uint256","name":"maxRatio","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"remainder","type":"address"},{"internalType":"uint256","name":"fyTokenToBuy","type":"uint256"},{"internalType":"uint256","name":"minRatio","type":"uint256"},{"internalType":"uint256","name":"maxRatio","type":"uint256"}],"name":"mintWithBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"retrieveBase","outputs":[{"internalType":"uint128","name":"retrieved","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"retrieveFYToken","outputs":[{"internalType":"uint128","name":"retrieved","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scaleFactor","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"min","type":"uint128"}],"name":"sellBase","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"baseIn","type":"uint128"}],"name":"sellBasePreview","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"min","type":"uint128"}],"name":"sellFYToken","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"fyTokenIn","type":"uint128"}],"name":"sellFYTokenPreview","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ts","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]