文件 1 的 26:AccessControl.sol
pragma solidity ^0.8.0;
contract AccessControl {
struct RoleData {
mapping (address => bool) members;
bytes4 adminRole;
}
mapping (bytes4 => RoleData) private _roles;
bytes4 public constant ROOT = 0x00000000;
bytes4 public constant ROOT4146650865 = 0x00000000;
bytes4 public constant LOCK = 0xFFFFFFFF;
bytes4 public constant LOCK8605463013 = 0xFFFFFFFF;
event RoleAdminChanged(bytes4 indexed role, bytes4 indexed newAdminRole);
event RoleGranted(bytes4 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes4 indexed role, address indexed account, address indexed sender);
constructor () {
_grantRole(ROOT, msg.sender);
_setRoleAdmin(LOCK, LOCK);
}
modifier auth() {
require (_hasRole(msg.sig, msg.sender), "Access denied");
_;
}
modifier admin(bytes4 role) {
require (_hasRole(_getRoleAdmin(role), msg.sender), "Only admin");
_;
}
function hasRole(bytes4 role, address account) external view returns (bool) {
return _hasRole(role, account);
}
function getRoleAdmin(bytes4 role) external view returns (bytes4) {
return _getRoleAdmin(role);
}
function setRoleAdmin(bytes4 role, bytes4 adminRole) external virtual admin(role) {
_setRoleAdmin(role, adminRole);
}
function grantRole(bytes4 role, address account) external virtual admin(role) {
_grantRole(role, account);
}
function grantRoles(bytes4[] memory roles, address account) external virtual {
for (uint256 i = 0; i < roles.length; i++) {
require (_hasRole(_getRoleAdmin(roles[i]), msg.sender), "Only admin");
_grantRole(roles[i], account);
}
}
function lockRole(bytes4 role) external virtual admin(role) {
_setRoleAdmin(role, LOCK);
}
function revokeRole(bytes4 role, address account) external virtual admin(role) {
_revokeRole(role, account);
}
function revokeRoles(bytes4[] memory roles, address account) external virtual {
for (uint256 i = 0; i < roles.length; i++) {
require (_hasRole(_getRoleAdmin(roles[i]), msg.sender), "Only admin");
_revokeRole(roles[i], account);
}
}
function renounceRole(bytes4 role, address account) external virtual {
require(account == msg.sender, "Renounce only for self");
_revokeRole(role, account);
}
function _hasRole(bytes4 role, address account) internal view returns (bool) {
return _roles[role].members[account];
}
function _getRoleAdmin(bytes4 role) internal view returns (bytes4) {
return _roles[role].adminRole;
}
function _setRoleAdmin(bytes4 role, bytes4 adminRole) internal virtual {
if (_getRoleAdmin(role) != adminRole) {
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, adminRole);
}
}
function _grantRole(bytes4 role, address account) internal {
if (!_hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, msg.sender);
}
}
function _revokeRole(bytes4 role, address account) internal {
if (_hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, msg.sender);
}
}
}
文件 2 的 26:AddressStringUtil.sol
pragma solidity >=0.5.0;
library AddressStringUtil {
function toAsciiString(address addr, uint256 len) internal pure returns (string memory) {
require(len % 2 == 0 && len > 0 && len <= 40, "AddressStringUtil: INVALID_LEN");
bytes memory s = new bytes(len);
uint256 addrNum = uint256(uint160(addr));
for (uint256 ii = 0; ii < len ; ii +=2) {
uint8 b = uint8(addrNum >> (4 * (38 - ii)));
s[ii] = char(b >> 4);
s[ii + 1] = char(b & 0x0f);
}
return string(s);
}
function char(uint8 b) private pure returns (bytes1 c) {
if (b < 10) {
return bytes1(b + 0x30);
} else {
return bytes1(b + 0x37);
}
}
}
文件 3 的 26: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);
}
}
文件 4 的 26:CastU256I128.sol
pragma solidity ^0.8.0;
library CastU256I128 {
function i128(uint256 x) internal pure returns(int128) {
require(x <= uint256(int256(type(int128).max)), "Cast overflow");
return int128(int256(x));
}
}
文件 5 的 26: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 的 26:CastU256U32.sol
pragma solidity ^0.8.0;
library CastU256U32 {
function u32(uint256 x) internal pure returns (uint32 y) {
require (x <= type(uint32).max, "Cast overflow");
y = uint32(x);
}
}
文件 7 的 26:DataTypes.sol
pragma solidity ^0.8.0;
import "./IFYToken.sol";
import "./IOracle.sol";
library DataTypes {
struct Series {
IFYToken fyToken;
bytes6 baseId;
uint32 maturity;
}
struct Debt {
uint96 max;
uint24 min;
uint8 dec;
uint128 sum;
}
struct SpotOracle {
IOracle oracle;
uint32 ratio;
}
struct Vault {
address owner;
bytes6 seriesId;
bytes6 ilkId;
}
struct Balances {
uint128 art;
uint128 ink;
}
}
文件 8 的 26: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;
}
}
文件 9 的 26: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);
}
}
文件 10 的 26:ERC20Rewards.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./ERC20Permit.sol";
import "../access/AccessControl.sol";
import "../utils/RevertMsgExtractor.sol";
import "../token/MinimalTransferHelper.sol";
import "../cast/CastU256U128.sol";
import "../cast/CastU256U32.sol";
contract ERC20Rewards is AccessControl, ERC20Permit {
using MinimalTransferHelper for IERC20;
using CastU256U32 for uint256;
using CastU256U128 for uint256;
event RewardsTokenSet(IERC20 token);
event RewardsSet(uint32 start, uint32 end, uint256 rate);
event RewardsPerTokenUpdated(uint256 accumulated);
event UserRewardsUpdated(address user, uint256 userRewards, uint256 paidRewardPerToken);
event Claimed(address receiver, uint256 claimed);
struct RewardsPeriod {
uint32 start;
uint32 end;
}
struct RewardsPerToken {
uint128 accumulated;
uint32 lastUpdated;
uint96 rate;
}
struct UserRewards {
uint128 accumulated;
uint128 checkpoint;
}
IERC20 public rewardsToken;
RewardsPeriod public rewardsPeriod;
RewardsPerToken public rewardsPerToken;
mapping (address => UserRewards) public rewards;
constructor(string memory name, string memory symbol, uint8 decimals)
ERC20Permit(name, symbol, decimals)
{ }
function earliest(uint32 x, uint32 y) internal pure returns (uint32 z) {
z = (x < y) ? x : y;
}
function setRewardsToken(IERC20 rewardsToken_)
external
auth
{
require(rewardsToken == IERC20(address(0)), "Rewards token already set");
rewardsToken = rewardsToken_;
emit RewardsTokenSet(rewardsToken_);
}
function setRewards(uint32 start, uint32 end, uint96 rate)
external
auth
{
require(
start <= end,
"Incorrect input"
);
require(
rewardsToken != IERC20(address(0)),
"Rewards token not set"
);
require(
block.timestamp.u32() < rewardsPeriod.start || block.timestamp.u32() > rewardsPeriod.end,
"Ongoing rewards"
);
rewardsPeriod.start = start;
rewardsPeriod.end = end;
rewardsPerToken.lastUpdated = start;
rewardsPerToken.rate = rate;
emit RewardsSet(start, end, rate);
}
function _updateRewardsPerToken() internal {
RewardsPerToken memory rewardsPerToken_ = rewardsPerToken;
RewardsPeriod memory rewardsPeriod_ = rewardsPeriod;
uint256 totalSupply_ = _totalSupply;
if (block.timestamp.u32() < rewardsPeriod_.start) return;
uint32 end = earliest(block.timestamp.u32(), rewardsPeriod_.end);
uint256 unaccountedTime = end - rewardsPerToken_.lastUpdated;
if (unaccountedTime == 0) return;
if (totalSupply_ != 0) rewardsPerToken_.accumulated = (rewardsPerToken_.accumulated + 1e18 * unaccountedTime * rewardsPerToken_.rate / totalSupply_).u128();
rewardsPerToken_.lastUpdated = end;
rewardsPerToken = rewardsPerToken_;
emit RewardsPerTokenUpdated(rewardsPerToken_.accumulated);
}
function _updateUserRewards(address user) internal returns (uint128) {
UserRewards memory userRewards_ = rewards[user];
RewardsPerToken memory rewardsPerToken_ = rewardsPerToken;
userRewards_.accumulated = (userRewards_.accumulated + _balanceOf[user] * (rewardsPerToken_.accumulated - userRewards_.checkpoint) / 1e18).u128();
userRewards_.checkpoint = rewardsPerToken_.accumulated;
rewards[user] = userRewards_;
emit UserRewardsUpdated(user, userRewards_.accumulated, userRewards_.checkpoint);
return userRewards_.accumulated;
}
function _mint(address dst, uint256 wad)
internal virtual override
returns (bool)
{
_updateRewardsPerToken();
_updateUserRewards(dst);
return super._mint(dst, wad);
}
function _burn(address src, uint256 wad)
internal virtual override
returns (bool)
{
_updateRewardsPerToken();
_updateUserRewards(src);
return super._burn(src, wad);
}
function _transfer(address src, address dst, uint wad) internal virtual override returns (bool) {
_updateRewardsPerToken();
_updateUserRewards(src);
_updateUserRewards(dst);
return super._transfer(src, dst, wad);
}
function claim(address to)
external
returns (uint256 claiming)
{
_updateRewardsPerToken();
claiming = _updateUserRewards(msg.sender);
rewards[msg.sender].accumulated = 0;
rewardsToken.safeTransfer(to, claiming);
emit Claimed(to, claiming);
}
}
文件 11 的 26:ICauldron.sol
pragma solidity ^0.8.0;
import "./IFYToken.sol";
import "./IOracle.sol";
import "./DataTypes.sol";
interface ICauldron {
function lendingOracles(bytes6 baseId) external view returns (IOracle);
function vaults(bytes12 vault) external view returns (DataTypes.Vault memory);
function series(bytes6 seriesId) external view returns (DataTypes.Series memory);
function assets(bytes6 assetsId) external view returns (address);
function balances(bytes12 vault) external view returns (DataTypes.Balances memory);
function debt(bytes6 baseId, bytes6 ilkId) external view returns (DataTypes.Debt memory);
function spotOracles(bytes6 baseId, bytes6 ilkId) external returns (DataTypes.SpotOracle memory);
function build(address owner, bytes12 vaultId, bytes6 seriesId, bytes6 ilkId) external returns (DataTypes.Vault memory);
function destroy(bytes12 vault) external;
function tweak(bytes12 vaultId, bytes6 seriesId, bytes6 ilkId) external returns (DataTypes.Vault memory);
function give(bytes12 vaultId, address receiver) external returns (DataTypes.Vault memory);
function stir(bytes12 from, bytes12 to, uint128 ink, uint128 art) external returns (DataTypes.Balances memory, DataTypes.Balances memory);
function pour(bytes12 vaultId, int128 ink, int128 art) external returns (DataTypes.Balances memory);
function roll(bytes12 vaultId, bytes6 seriesId, int128 art) external returns (DataTypes.Vault memory, DataTypes.Balances memory);
function slurp(bytes12 vaultId, uint128 ink, uint128 art) external returns (DataTypes.Balances memory);
function debtFromBase(bytes6 seriesId, uint128 base) external returns (uint128 art);
function debtToBase(bytes6 seriesId, uint128 art) external returns (uint128 base);
function mature(bytes6 seriesId) external;
function accrual(bytes6 seriesId) external returns (uint256);
function level(bytes12 vaultId) external returns (int256);
}
文件 12 的 26: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);
}
文件 13 的 26: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);
}
文件 14 的 26: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);
}
文件 15 的 26: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;
}
文件 16 的 26:IJoin.sol
pragma solidity ^0.8.0;
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";
interface IJoin {
function asset() external view returns (address);
function join(address user, uint128 wad) external returns (uint128);
function exit(address user, uint128 wad) external returns (uint128);
}
文件 17 的 26:ILadle.sol
pragma solidity ^0.8.0;
import "./IJoin.sol";
import "./ICauldron.sol";
interface ILadle {
function joins(bytes6) external view returns (IJoin);
function cauldron() external view returns (ICauldron);
function build(bytes6 seriesId, bytes6 ilkId, uint8 salt) external returns (bytes12 vaultId, DataTypes.Vault memory vault);
function destroy(bytes12 vaultId) external;
function pour(bytes12 vaultId, address to, int128 ink, int128 art) external;
function close(bytes12 vaultId, address to, int128 ink, int128 art) external;
}
文件 18 的 26:IOracle.sol
pragma solidity ^0.8.0;
interface IOracle {
function peek(bytes32 base, bytes32 quote, uint256 amount) external view returns (uint256 value, uint256 updateTime);
function get(bytes32 base, bytes32 quote, uint256 amount) external returns (uint256 value, uint256 updateTime);
}
文件 19 的 26: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);
}
文件 20 的 26: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);
}
}
}
}
文件 21 的 26: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));
}
}
文件 22 的 26: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));
}
}
文件 23 的 26:SafeERC20Namer.sol
pragma solidity >=0.5.0;
import "../token/IERC20Metadata.sol";
import "../utils/AddressStringUtil.sol";
library SafeERC20Namer {
function bytes32ToString(bytes32 x) private pure returns (string memory) {
bytes memory bytesString = new bytes(32);
uint256 charCount = 0;
for (uint256 j = 0; j < 32; j++) {
bytes1 char = x[j];
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (uint256 j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
function parseStringData(bytes memory b) private pure returns (string memory) {
uint256 charCount = 0;
for (uint256 i = 32; i < 64; i++) {
charCount <<= 8;
charCount += uint8(b[i]);
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (uint256 i = 0; i < charCount; i++) {
bytesStringTrimmed[i] = b[i + 64];
}
return string(bytesStringTrimmed);
}
function addressToName(address token) private pure returns (string memory) {
return AddressStringUtil.toAsciiString(token, 40);
}
function addressToSymbol(address token) private pure returns (string memory) {
return AddressStringUtil.toAsciiString(token, 6);
}
function callAndParseStringReturn(address token, bytes4 selector) private view returns (string memory) {
(bool success, bytes memory data) = token.staticcall(abi.encodeWithSelector(selector));
if (!success || data.length == 0) {
return "";
}
if (data.length == 32) {
bytes32 decoded = abi.decode(data, (bytes32));
return bytes32ToString(decoded);
} else if (data.length > 64) {
return abi.decode(data, (string));
}
return "";
}
function tokenSymbol(address token) public view returns (string memory) {
string memory symbol = callAndParseStringReturn(token, IERC20Metadata.symbol.selector);
if (bytes(symbol).length == 0) {
return addressToSymbol(token);
}
return symbol;
}
function tokenName(address token) public view returns (string memory) {
string memory name = callAndParseStringReturn(token, IERC20Metadata.name.selector);
if (bytes(name).length == 0) {
return addressToName(token);
}
return name;
}
function tokenDecimals(address token) public view returns (uint8) {
(bool success, bytes memory data) = token.staticcall(abi.encodeWithSelector(IERC20Metadata.decimals.selector));
return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;
}
}
文件 24 的 26:Strategy.sol
pragma solidity 0.8.6;
import "@yield-protocol/utils-v2/contracts/access/AccessControl.sol";
import "@yield-protocol/utils-v2/contracts/token/SafeERC20Namer.sol";
import "@yield-protocol/utils-v2/contracts/token/MinimalTransferHelper.sol";
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";
import "@yield-protocol/utils-v2/contracts/token/ERC20Rewards.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU256I128.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU128I128.sol";
import "@yield-protocol/vault-interfaces/DataTypes.sol";
import "@yield-protocol/vault-interfaces/ICauldron.sol";
import "@yield-protocol/vault-interfaces/ILadle.sol";
import "@yield-protocol/yieldspace-interfaces/IPool.sol";
import "@yield-protocol/yieldspace-v2/contracts/extensions/YieldMathExtensions.sol";
library DivUp {
function divUp(uint256 a, uint256 b) internal pure returns(uint256 c) {
a % b == 0 ? c = a / b : c = a / b + 1;
}
}
contract Strategy is AccessControl, ERC20Rewards {
using DivUp for uint256;
using MinimalTransferHelper for IERC20;
using YieldMathExtensions for IPool;
using CastU256U128 for uint256;
using CastU256I128 for uint256;
using CastU128I128 for uint128;
event YieldSet(ILadle ladle, ICauldron cauldron);
event TokenJoinReset(address join);
event TokenIdSet(bytes6 id);
event NextPoolSet(IPool indexed pool, bytes6 indexed seriesId);
event PoolEnded(address pool);
event PoolStarted(address pool);
IERC20 public immutable base;
bytes6 public baseId;
address public baseJoin;
ILadle public ladle;
ICauldron public cauldron;
IPool public pool;
bytes6 public seriesId;
IFYToken public fyToken;
IPool public nextPool;
bytes6 public nextSeriesId;
uint256 public cached;
mapping (address => uint128) public invariants;
constructor(string memory name, string memory symbol, ILadle ladle_, IERC20 base_, bytes6 baseId_)
ERC20Rewards(name, symbol, SafeERC20Namer.tokenDecimals(address(base_)))
{
require(
ladle_.cauldron().assets(baseId_) == address(base_),
"Mismatched baseId"
);
base = base_;
baseId = baseId_;
baseJoin = address(ladle_.joins(baseId_));
ladle = ladle_;
cauldron = ladle_.cauldron();
}
modifier poolSelected() {
require (
pool != IPool(address(0)),
"Pool not selected"
);
_;
}
modifier poolNotSelected() {
require (
pool == IPool(address(0)),
"Pool selected"
);
_;
}
modifier afterMaturity() {
require (
uint32(block.timestamp) >= fyToken.maturity(),
"Only after maturity"
);
_;
}
function setYield(ILadle ladle_)
external
poolNotSelected
auth
{
ladle = ladle_;
ICauldron cauldron_ = ladle_.cauldron();
cauldron = cauldron_;
emit YieldSet(ladle_, cauldron_);
}
function setTokenId(bytes6 baseId_)
external
poolNotSelected
auth
{
require(
ladle.cauldron().assets(baseId_) == address(base),
"Mismatched baseId"
);
baseId = baseId_;
emit TokenIdSet(baseId_);
}
function resetTokenJoin()
external
poolNotSelected
auth
{
baseJoin = address(ladle.joins(baseId));
emit TokenJoinReset(baseJoin);
}
function setNextPool(IPool pool_, bytes6 seriesId_)
external
auth
{
require(
base == pool_.base(),
"Mismatched base"
);
DataTypes.Series memory series = cauldron.series(seriesId_);
require(
series.fyToken == pool_.fyToken(),
"Mismatched seriesId"
);
nextPool = pool_;
nextSeriesId = seriesId_;
emit NextPoolSet(pool_, seriesId_);
}
function startPool(uint256 minRatio, uint256 maxRatio)
external
auth
poolNotSelected
{
IPool nextPool_ = nextPool;
require(nextPool_ != IPool(address(0)), "Next pool not set");
IPool pool_ = nextPool_;
IFYToken fyToken_ = pool_.fyToken();
bytes6 seriesId_ = nextSeriesId;
pool = pool_;
fyToken = fyToken_;
seriesId = seriesId_;
delete nextPool;
delete nextSeriesId;
uint256 baseBalance = base.balanceOf(address(this));
require(baseBalance > 0, "No funds to start with");
uint256 baseInPool = base.balanceOf(address(pool_));
uint256 fyTokenInPool = fyToken_.balanceOf(address(pool_));
uint256 baseToPool = (baseBalance * baseInPool).divUp(baseInPool + fyTokenInPool);
uint256 fyTokenToPool = baseBalance - baseToPool;
base.safeTransfer(baseJoin, fyTokenToPool);
fyToken.mintWithUnderlying(address(pool_), fyTokenToPool);
base.safeTransfer(address(pool_), baseToPool);
(,, cached) = pool_.mint(address(this), address(this), minRatio, maxRatio);
if (_totalSupply == 0) _mint(msg.sender, cached);
invariants[address(pool_)] = pool_.invariant();
emit PoolStarted(address(pool_));
}
function endPool()
external
afterMaturity
{
IPool pool_ = pool;
IFYToken fyToken_ = fyToken;
uint256 toDivest = pool_.balanceOf(address(this));
IERC20(address(pool_)).safeTransfer(address(pool_), toDivest);
(,, uint256 fyTokenDivested) = pool_.burn(address(this), address(this), 0, type(uint256).max);
IERC20(address(fyToken_)).safeTransfer(address(fyToken_), fyTokenDivested);
fyToken_.redeem(address(this), fyTokenDivested);
emit PoolEnded(address(pool_));
delete pool;
delete fyToken;
delete seriesId;
delete cached;
}
function mint(address to)
external
poolSelected
returns (uint256 minted)
{
uint256 cached_ = cached;
uint256 deposit = pool.balanceOf(address(this)) - cached_;
minted = _totalSupply * deposit / cached_;
cached = cached_ + deposit;
_mint(to, minted);
}
function burn(address to)
external
poolSelected
returns (uint256 withdrawal)
{
uint256 cached_ = cached;
uint256 burnt = _balanceOf[address(this)];
withdrawal = cached_ * burnt / _totalSupply;
cached = cached_ - withdrawal;
_burn(address(this), burnt);
IERC20(address(pool)).safeTransfer(to, withdrawal);
}
function burnForBase(address to)
external
poolNotSelected
returns (uint256 withdrawal)
{
uint256 burnt = _balanceOf[address(this)];
withdrawal = base.balanceOf(address(this)) * burnt / _totalSupply;
_burn(address(this), burnt);
base.safeTransfer(to, withdrawal);
}
}
文件 25 的 26: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);
}
}
}
文件 26 的 26:YieldMathExtensions.sol
pragma solidity 0.8.6;
import "@yield-protocol/yieldspace-interfaces/IPool.sol";
import "../YieldMath.sol";
library YieldMathExtensions {
function invariant(IPool pool) external view returns (uint128) {
uint32 maturity = pool.maturity();
uint32 timeToMaturity = (maturity > uint32(block.timestamp)) ? maturity - uint32(block.timestamp) : 0;
return YieldMath.invariant(
pool.getBaseBalance(),
pool.getFYTokenBalance(),
pool.totalSupply(),
timeToMaturity,
pool.ts()
);
}
function maxFYTokenOut(IPool pool) external view returns (uint128) {
(uint112 _baseCached, uint112 _fyTokenCached,) = pool.getCache();
uint96 scaleFactor = pool.scaleFactor();
return YieldMath.maxFYTokenOut(
_baseCached * scaleFactor,
_fyTokenCached * scaleFactor,
pool.maturity() - uint32(block.timestamp),
pool.ts(),
pool.g1()
) / scaleFactor;
}
function maxFYTokenIn(IPool pool) external view returns (uint128) {
(uint112 _baseCached, uint112 _fyTokenCached,) = pool.getCache();
uint96 scaleFactor = pool.scaleFactor();
return YieldMath.maxFYTokenIn(
_baseCached * scaleFactor,
_fyTokenCached * scaleFactor,
pool.maturity() - uint32(block.timestamp),
pool.ts(),
pool.g2()
) / scaleFactor;
}
function maxBaseIn(IPool pool) external view returns (uint128) {
(uint112 _baseCached, uint112 _fyTokenCached,) = pool.getCache();
uint96 scaleFactor = pool.scaleFactor();
return YieldMath.maxBaseIn(
_baseCached * scaleFactor,
_fyTokenCached * scaleFactor,
pool.maturity() - uint32(block.timestamp),
pool.ts(),
pool.g1()
) / scaleFactor;
}
function maxBaseOut(IPool pool) external view returns (uint128) {
(uint112 _baseCached, uint112 _fyTokenCached,) = pool.getCache();
uint96 scaleFactor = pool.scaleFactor();
return YieldMath.maxBaseOut(
_baseCached * scaleFactor,
_fyTokenCached * scaleFactor,
pool.maturity() - uint32(block.timestamp),
pool.ts(),
pool.g2()
) / scaleFactor;
}
}
{
"compilationTarget": {
"@yield-protocol/strategy-v2/contracts/Strategy.sol": "Strategy"
},
"evmVersion": "berlin",
"libraries": {
"@yield-protocol/utils-v2/contracts/token/SafeERC20Namer.sol:SafeERC20Namer": "0xbd6bee8d3b9d1ee6b8105bed11a61fdcae4bff8b",
"@yield-protocol/yieldspace-v2/contracts/extensions/YieldMathExtensions.sol:YieldMathExtensions": "0xc445d7e3cdc96840439560675ca9023204ea9acd"
},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"contract ILadle","name":"ladle_","type":"address"},{"internalType":"contract IERC20","name":"base_","type":"address"},{"internalType":"bytes6","name":"baseId_","type":"bytes6"}],"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":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimed","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IPool","name":"pool","type":"address"},{"indexed":true,"internalType":"bytes6","name":"seriesId","type":"bytes6"}],"name":"NextPoolSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"PoolEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"PoolStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"accumulated","type":"uint256"}],"name":"RewardsPerTokenUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"start","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"end","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"RewardsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IERC20","name":"token","type":"address"}],"name":"RewardsTokenSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"role","type":"bytes4"},{"indexed":true,"internalType":"bytes4","name":"newAdminRole","type":"bytes4"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"role","type":"bytes4"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"role","type":"bytes4"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes6","name":"id","type":"bytes6"}],"name":"TokenIdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"join","type":"address"}],"name":"TokenJoinReset","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"userRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paidRewardPerToken","type":"uint256"}],"name":"UserRewardsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ILadle","name":"ladle","type":"address"},{"indexed":false,"internalType":"contract ICauldron","name":"cauldron","type":"address"}],"name":"YieldSet","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCK","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCK8605463013","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT4146650865","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"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":[],"name":"baseId","outputs":[{"internalType":"bytes6","name":"","type":"bytes6"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseJoin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burn","outputs":[{"internalType":"uint256","name":"withdrawal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burnForBase","outputs":[{"internalType":"uint256","name":"withdrawal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cached","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cauldron","outputs":[{"internalType":"contract ICauldron","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[{"internalType":"uint256","name":"claiming","type":"uint256"}],"stateMutability":"nonpayable","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":"endPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fyToken","outputs":[{"internalType":"contract IFYToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"roles","type":"bytes4[]"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"invariants","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ladle","outputs":[{"internalType":"contract ILadle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"}],"name":"lockRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"minted","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextPool","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextSeriesId","outputs":[{"internalType":"bytes6","name":"","type":"bytes6"}],"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":[],"name":"pool","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetTokenJoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"roles","type":"bytes4[]"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint128","name":"accumulated","type":"uint128"},{"internalType":"uint128","name":"checkpoint","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerToken","outputs":[{"internalType":"uint128","name":"accumulated","type":"uint128"},{"internalType":"uint32","name":"lastUpdated","type":"uint32"},{"internalType":"uint96","name":"rate","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPeriod","outputs":[{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seriesId","outputs":[{"internalType":"bytes6","name":"","type":"bytes6"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IPool","name":"pool_","type":"address"},{"internalType":"bytes6","name":"seriesId_","type":"bytes6"}],"name":"setNextPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"},{"internalType":"uint96","name":"rate","type":"uint96"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"rewardsToken_","type":"address"}],"name":"setRewardsToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"bytes4","name":"adminRole","type":"bytes4"}],"name":"setRoleAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes6","name":"baseId_","type":"bytes6"}],"name":"setTokenId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ILadle","name":"ladle_","type":"address"}],"name":"setYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minRatio","type":"uint256"},{"internalType":"uint256","name":"maxRatio","type":"uint256"}],"name":"startPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]