Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
Overview
Max Total Supply
125.770477228476838662 YSETH6MMS
Holders
352
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
0.004070906514622601 YSETH6MMSValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Strategy
Compiler Version
v0.8.6+commit.11564f7e
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 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; } } /// @dev The Pool contract exchanges base for fyToken at a price defined by a specific formula. contract Strategy is AccessControl, ERC20Rewards { using DivUp for uint256; using MinimalTransferHelper for IERC20; using YieldMathExtensions for IPool; using CastU256U128 for uint256; // Inherited from ERC20Rewards 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; // Base token for this strategy bytes6 public baseId; // Identifier for the base token in Yieldv2 address public baseJoin; // Yield v2 Join to deposit token when borrowing ILadle public ladle; // Gateway to the Yield v2 Collateralized Debt Engine ICauldron public cauldron; // Accounts in the Yield v2 Collateralized Debt Engine IPool public pool; // Current pool that this strategy invests in bytes6 public seriesId; // SeriesId for the current pool in Yield v2 IFYToken public fyToken; // Current fyToken for this strategy IPool public nextPool; // Next pool that this strategy will invest in bytes6 public nextSeriesId; // SeriesId for the next pool in Yield v2 uint256 public cached; // LP tokens owned by the strategy after the last operation mapping (address => uint128) public invariants; // Value of pool invariant at start time constructor(string memory name, string memory symbol, ILadle ladle_, IERC20 base_, bytes6 baseId_) ERC20Rewards(name, symbol, SafeERC20Namer.tokenDecimals(address(base_))) { // The strategy asset inherits the decimals of its base, that matches the decimals of the fyToken and pool 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" ); _; } /// @dev Set a new Ladle and Cauldron /// @notice Use with extreme caution, only for Ladle replacements function setYield(ILadle ladle_) external poolNotSelected auth { ladle = ladle_; ICauldron cauldron_ = ladle_.cauldron(); cauldron = cauldron_; emit YieldSet(ladle_, cauldron_); } /// @dev Set a new base token id /// @notice Use with extreme caution, only for token reconfigurations in Cauldron function setTokenId(bytes6 baseId_) external poolNotSelected auth { require( ladle.cauldron().assets(baseId_) == address(base), "Mismatched baseId" ); baseId = baseId_; emit TokenIdSet(baseId_); } /// @dev Reset the base token join /// @notice Use with extreme caution, only for Join replacements function resetTokenJoin() external poolNotSelected auth { baseJoin = address(ladle.joins(baseId)); emit TokenJoinReset(baseJoin); } /// @dev Set the next pool to invest in 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_); } /// @dev Start the strategy investments in the next pool /// @param minRatio Minimum allowed ratio between the reserves of the next pool, as a fixed point number with 18 decimals (base/fyToken) /// @param maxRatio Maximum allowed ratio between the reserves of the next pool, as a fixed point number with 18 decimals (base/fyToken) /// @notice When calling this function for the first pool, some underlying needs to be transferred to the strategy first, using a batchable router. function startPool(uint256 minRatio, uint256 maxRatio) external auth poolNotSelected { IPool nextPool_ = nextPool; require(nextPool_ != IPool(address(0)), "Next pool not set"); // Caching IPool pool_ = nextPool_; IFYToken fyToken_ = pool_.fyToken(); bytes6 seriesId_ = nextSeriesId; pool = pool_; fyToken = fyToken_; seriesId = seriesId_; delete nextPool; delete nextSeriesId; // Find pool proportion p = tokenReserves/(tokenReserves + fyTokenReserves) // Deposit (investment * p) base to borrow (investment * p) fyToken // (investment * p) fyToken + (investment * (1 - p)) base = investment // (investment * p) / ((investment * p) + (investment * (1 - p))) = p // (investment * (1 - p)) / ((investment * p) + (investment * (1 - p))) = 1 - p uint256 baseBalance = base.balanceOf(address(this)); require(baseBalance > 0, "No funds to start with"); // The Pool mints based on cached values, not actual ones. Consider bundling a `pool.sync` // call if they differ. A griefing attack exists by donating one fyToken wei to the pool // before `startPool`, solved the same way. uint256 baseInPool = base.balanceOf(address(pool_)); uint256 fyTokenInPool = fyToken_.balanceOf(address(pool_)); uint256 baseToPool = (baseBalance * baseInPool).divUp(baseInPool + fyTokenInPool); // Rounds up uint256 fyTokenToPool = baseBalance - baseToPool; // fyTokenToPool is rounded down // Mint fyToken with underlying base.safeTransfer(baseJoin, fyTokenToPool); fyToken.mintWithUnderlying(address(pool_), fyTokenToPool); // Mint LP tokens with (investment * p) fyToken and (investment * (1 - p)) base base.safeTransfer(address(pool_), baseToPool); (,, cached) = pool_.mint(address(this), address(this), minRatio, maxRatio); if (_totalSupply == 0) _mint(msg.sender, cached); // Initialize the strategy if needed invariants[address(pool_)] = pool_.invariant(); // Cache the invariant to help the frontend calculate profits emit PoolStarted(address(pool_)); } /// @dev Divest out of a pool once it has matured function endPool() external afterMaturity { // Caching IPool pool_ = pool; IFYToken fyToken_ = fyToken; uint256 toDivest = pool_.balanceOf(address(this)); // Burn lpTokens IERC20(address(pool_)).safeTransfer(address(pool_), toDivest); (,, uint256 fyTokenDivested) = pool_.burn(address(this), address(this), 0, type(uint256).max); // We don't care about slippage, because the strategy holds to maturity // Redeem any fyToken IERC20(address(fyToken_)).safeTransfer(address(fyToken_), fyTokenDivested); fyToken_.redeem(address(this), fyTokenDivested); emit PoolEnded(address(pool_)); // Clear up delete pool; delete fyToken; delete seriesId; delete cached; } /// @dev Mint strategy tokens. /// @notice The lp tokens that the user contributes need to have been transferred previously, using a batchable router. function mint(address to) external poolSelected returns (uint256 minted) { // minted = supply * value(deposit) / value(strategy) uint256 cached_ = cached; uint256 deposit = pool.balanceOf(address(this)) - cached_; minted = _totalSupply * deposit / cached_; cached = cached_ + deposit; _mint(to, minted); } /// @dev Burn strategy tokens to withdraw lp tokens. The lp tokens obtained won't be of the same pool that the investor deposited, /// if the strategy has swapped to another pool. /// @notice The strategy tokens that the user burns need to have been transferred previously, using a batchable router. function burn(address to) external poolSelected returns (uint256 withdrawal) { // strategy * burnt/supply = 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); } /// @dev Burn strategy tokens to withdraw base tokens. It can be called only when a pool is not selected. /// @notice The strategy tokens that the user burns need to have been transferred previously, using a batchable router. function burnForBase(address to) external poolNotSelected returns (uint256 withdrawal) { // strategy * burnt/supply = withdrawal uint256 burnt = _balanceOf[address(this)]; withdrawal = base.balanceOf(address(this)) * burnt / _totalSupply; _burn(address(this), burnt); base.safeTransfer(to, withdrawal); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. * * Roles are referred to by their `bytes4` identifier. These are expected to be the * signatures for all the functions in the contract. Special roles should be exposed * in the external API and be unique: * * ``` * bytes4 public constant ROOT = 0x00000000; * ``` * * Roles represent restricted access to a function call. For that purpose, use {auth}: * * ``` * function foo() public auth { * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `ROOT`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {setRoleAdmin}. * * WARNING: The `ROOT` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ 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; // Collision protection for ROOT, test with ROOT12007226833() bytes4 public constant LOCK = 0xFFFFFFFF; // Used to disable further permissioning of a function bytes4 public constant LOCK8605463013 = 0xFFFFFFFF; // Collision protection for LOCK, test with LOCK10462387368() /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role * * `ROOT` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes4 indexed role, bytes4 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. */ event RoleGranted(bytes4 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes4 indexed role, address indexed account, address indexed sender); /** * @dev Give msg.sender the ROOT role and create a LOCK role with itself as the admin role and no members. * Calling setRoleAdmin(msg.sig, LOCK) means no one can grant that msg.sig role anymore. */ constructor () { _grantRole(ROOT, msg.sender); // Grant ROOT to msg.sender _setRoleAdmin(LOCK, LOCK); // Create the LOCK role by setting itself as its own admin, creating an independent role tree } /** * @dev Each function in the contract has its own role, identified by their msg.sig signature. * ROOT can give and remove access to each function, lock any further access being granted to * a specific action, or even create other roles to delegate admin control over a function. */ modifier auth() { require (_hasRole(msg.sig, msg.sender), "Access denied"); _; } /** * @dev Allow only if the caller has been granted the admin role of `role`. */ modifier admin(bytes4 role) { require (_hasRole(_getRoleAdmin(role), msg.sender), "Only admin"); _; } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes4 role, address account) external view returns (bool) { return _hasRole(role, account); } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes4 role) external view returns (bytes4) { return _getRoleAdmin(role); } /** * @dev Sets `adminRole` as ``role``'s admin role. * If ``role``'s admin role is not `adminRole` emits a {RoleAdminChanged} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function setRoleAdmin(bytes4 role, bytes4 adminRole) external virtual admin(role) { _setRoleAdmin(role, adminRole); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes4 role, address account) external virtual admin(role) { _grantRole(role, account); } /** * @dev Grants all of `role` in `roles` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - For each `role` in `roles`, the caller must have ``role``'s admin role. */ 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); } } /** * @dev Sets LOCK as ``role``'s admin role. LOCK has no members, so this disables admin management of ``role``. * Emits a {RoleAdminChanged} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function lockRole(bytes4 role) external virtual admin(role) { _setRoleAdmin(role, LOCK); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes4 role, address account) external virtual admin(role) { _revokeRole(role, account); } /** * @dev Revokes all of `role` in `roles` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - For each `role` in `roles`, the caller must have ``role``'s admin role. */ 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); } } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `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); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; import "../token/IERC20Metadata.sol"; import "../utils/AddressStringUtil.sol"; // produces token descriptors from inconsistent or absent ERC20 symbol implementations that can return string or bytes32 // this library will always produce a string symbol to represent the token 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); } // assumes the data is in position 2 function parseStringData(bytes memory b) private pure returns (string memory) { uint256 charCount = 0; // first parse the charCount out of the data 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); } // uses a heuristic to produce a token name from the address // the heuristic returns the full hex of the address string in upper case function addressToName(address token) private pure returns (string memory) { return AddressStringUtil.toAsciiString(token, 40); } // uses a heuristic to produce a token symbol from the address // the heuristic returns the first 6 hex of the address string in upper case function addressToSymbol(address token) private pure returns (string memory) { return AddressStringUtil.toAsciiString(token, 6); } // calls an external view token contract method that returns a symbol or name, and parses the output into a string function callAndParseStringReturn(address token, bytes4 selector) private view returns (string memory) { (bool success, bytes memory data) = token.staticcall(abi.encodeWithSelector(selector)); // if not implemented, or returns empty data, return empty string if (!success || data.length == 0) { return ""; } // bytes32 data always has length 32 if (data.length == 32) { bytes32 decoded = abi.decode(data, (bytes32)); return bytes32ToString(decoded); } else if (data.length > 64) { return abi.decode(data, (string)); } return ""; } // attempts to extract the token symbol. if it does not implement symbol, returns a symbol derived from the address function tokenSymbol(address token) public view returns (string memory) { string memory symbol = callAndParseStringReturn(token, IERC20Metadata.symbol.selector); if (bytes(symbol).length == 0) { // fallback to 6 uppercase hex of address return addressToSymbol(token); } return symbol; } // attempts to extract the token name. if it does not implement name, returns a name derived from the address function tokenName(address token) public view returns (string memory) { string memory name = callAndParseStringReturn(token, IERC20Metadata.name.selector); if (bytes(name).length == 0) { // fallback to full hex of address return addressToName(token); } return name; } /// @notice Provides a safe ERC20.decimals version which returns '18' as fallback value. /// @param token The address of the ERC-20 token contract. /// @return (uint8) Token decimals. 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; } }
// SPDX-License-Identifier: MIT // Taken from https://github.com/Uniswap/uniswap-lib/blob/master/contracts/libraries/TransferHelper.sol pragma solidity >=0.6.0; import "./IERC20.sol"; import "../utils/RevertMsgExtractor.sol"; // helper methods for transferring ERC20 tokens that do not consistently return true/false library MinimalTransferHelper { /// @notice Transfers tokens from msg.sender to a recipient /// @dev Errors with the underlying revert message if transfer fails /// @param token The contract address of the token which will be transferred /// @param to The recipient of the transfer /// @param value The value of the transfer 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)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT 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"; /// @dev A token inheriting from ERC20Rewards will reward token holders with a rewards token. /// The rewarded amount will be a fixed wei per second, distributed proportionally to token holders /// by the size of their holdings. 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; // Start time for the current rewardsToken schedule uint32 end; // End time for the current rewardsToken schedule } struct RewardsPerToken { uint128 accumulated; // Accumulated rewards per token for the period, scaled up by 1e18 uint32 lastUpdated; // Last time the rewards per token accumulator was updated uint96 rate; // Wei rewarded per second among all token holders } struct UserRewards { uint128 accumulated; // Accumulated rewards for the user until the checkpoint uint128 checkpoint; // RewardsPerToken the last time the user rewards were updated } IERC20 public rewardsToken; // Token used as rewards RewardsPeriod public rewardsPeriod; // Period in which rewards are accumulated by users RewardsPerToken public rewardsPerToken; // Accumulator to track rewards per token mapping (address => UserRewards) public rewards; // Rewards accumulated by users constructor(string memory name, string memory symbol, uint8 decimals) ERC20Permit(name, symbol, decimals) { } /// @dev Return the earliest of two timestamps function earliest(uint32 x, uint32 y) internal pure returns (uint32 z) { z = (x < y) ? x : y; } /// @dev Set a rewards token. /// @notice Careful, this can only be done once. function setRewardsToken(IERC20 rewardsToken_) external auth { require(rewardsToken == IERC20(address(0)), "Rewards token already set"); rewardsToken = rewardsToken_; emit RewardsTokenSet(rewardsToken_); } /// @dev Set a rewards schedule function setRewards(uint32 start, uint32 end, uint96 rate) external auth { require( start <= end, "Incorrect input" ); require( rewardsToken != IERC20(address(0)), "Rewards token not set" ); // A new rewards program can be set if one is not running require( block.timestamp.u32() < rewardsPeriod.start || block.timestamp.u32() > rewardsPeriod.end, "Ongoing rewards" ); rewardsPeriod.start = start; rewardsPeriod.end = end; // If setting up a new rewards program, the rewardsPerToken.accumulated is used and built upon // New rewards start accumulating from the new rewards program start // Any unaccounted rewards from last program can still be added to the user rewards // Any unclaimed rewards can still be claimed rewardsPerToken.lastUpdated = start; rewardsPerToken.rate = rate; emit RewardsSet(start, end, rate); } /// @dev Update the rewards per token accumulator. /// @notice Needs to be called on each liquidity event function _updateRewardsPerToken() internal { RewardsPerToken memory rewardsPerToken_ = rewardsPerToken; RewardsPeriod memory rewardsPeriod_ = rewardsPeriod; uint256 totalSupply_ = _totalSupply; // We skip the update if the program hasn't started if (block.timestamp.u32() < rewardsPeriod_.start) return; // Find out the unaccounted time uint32 end = earliest(block.timestamp.u32(), rewardsPeriod_.end); uint256 unaccountedTime = end - rewardsPerToken_.lastUpdated; // Cast to uint256 to avoid overflows later on if (unaccountedTime == 0) return; // We skip the storage changes if already updated in the same block // Calculate and update the new value of the accumulator. unaccountedTime casts it into uint256, which is desired. // If the first mint happens mid-program, we don't update the accumulator, no one gets the rewards for that period. if (totalSupply_ != 0) rewardsPerToken_.accumulated = (rewardsPerToken_.accumulated + 1e18 * unaccountedTime * rewardsPerToken_.rate / totalSupply_).u128(); // The rewards per token are scaled up for precision rewardsPerToken_.lastUpdated = end; rewardsPerToken = rewardsPerToken_; emit RewardsPerTokenUpdated(rewardsPerToken_.accumulated); } /// @dev Accumulate rewards for an user. /// @notice Needs to be called on each liquidity event, or when user balances change. function _updateUserRewards(address user) internal returns (uint128) { UserRewards memory userRewards_ = rewards[user]; RewardsPerToken memory rewardsPerToken_ = rewardsPerToken; // Calculate and update the new value user reserves. _balanceOf[user] casts it into uint256, which is desired. userRewards_.accumulated = (userRewards_.accumulated + _balanceOf[user] * (rewardsPerToken_.accumulated - userRewards_.checkpoint) / 1e18).u128(); // We must scale down the rewards by the precision factor userRewards_.checkpoint = rewardsPerToken_.accumulated; rewards[user] = userRewards_; emit UserRewardsUpdated(user, userRewards_.accumulated, userRewards_.checkpoint); return userRewards_.accumulated; } /// @dev Mint tokens, after accumulating rewards for an user and update the rewards per token accumulator. function _mint(address dst, uint256 wad) internal virtual override returns (bool) { _updateRewardsPerToken(); _updateUserRewards(dst); return super._mint(dst, wad); } /// @dev Burn tokens, after accumulating rewards for an user and update the rewards per token accumulator. function _burn(address src, uint256 wad) internal virtual override returns (bool) { _updateRewardsPerToken(); _updateUserRewards(src); return super._burn(src, wad); } /// @dev Transfer tokens, after updating rewards for source and destination. function _transfer(address src, address dst, uint wad) internal virtual override returns (bool) { _updateRewardsPerToken(); _updateUserRewards(src); _updateUserRewards(dst); return super._transfer(src, dst, wad); } /// @dev Claim all rewards from caller into a given address function claim(address to) external returns (uint256 claiming) { _updateRewardsPerToken(); claiming = _updateUserRewards(msg.sender); rewards[msg.sender].accumulated = 0; // A Claimed event implies the rewards were set to zero rewardsToken.safeTransfer(to, claiming); emit Claimed(to, claiming); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; library CastU256I128 { /// @dev Safe casting from uint256 to int256 function i128(uint256 x) internal pure returns(int128) { require(x <= uint256(int256(type(int128).max)), "Cast overflow"); return int128(int256(x)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; library CastU128I128 { /// @dev Safely cast an uint128 to an int128 function i128(uint128 x) internal pure returns (int128 y) { require (x <= uint128(type(int128).max), "Cast overflow"); y = int128(x); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IFYToken.sol"; import "./IOracle.sol"; library DataTypes { struct Series { IFYToken fyToken; // Redeemable token for the series. bytes6 baseId; // Asset received on redemption. uint32 maturity; // Unix time at which redemption becomes possible. // bytes2 free } struct Debt { uint96 max; // Maximum debt accepted for a given underlying, across all series uint24 min; // Minimum debt accepted for a given underlying, across all series uint8 dec; // Multiplying factor (10**dec) for max and min uint128 sum; // Current debt for a given underlying, across all series } struct SpotOracle { IOracle oracle; // Address for the spot price oracle uint32 ratio; // Collateralization ratio to multiply the price for // bytes8 free } struct Vault { address owner; bytes6 seriesId; // Each vault is related to only one series, which also determines the underlying. bytes6 ilkId; // Asset accepted as collateral } struct Balances { uint128 art; // Debt amount uint128 ink; // Collateral amount } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IFYToken.sol"; import "./IOracle.sol"; import "./DataTypes.sol"; interface ICauldron { /// @dev Variable rate lending oracle for an underlying function lendingOracles(bytes6 baseId) external view returns (IOracle); /// @dev An user can own one or more Vaults, with each vault being able to borrow from a single series. function vaults(bytes12 vault) external view returns (DataTypes.Vault memory); /// @dev Series available in Cauldron. function series(bytes6 seriesId) external view returns (DataTypes.Series memory); /// @dev Assets available in Cauldron. function assets(bytes6 assetsId) external view returns (address); /// @dev Each vault records debt and collateral balances_. function balances(bytes12 vault) external view returns (DataTypes.Balances memory); /// @dev Max, min and sum of debt per underlying and collateral. function debt(bytes6 baseId, bytes6 ilkId) external view returns (DataTypes.Debt memory); // @dev Spot price oracle addresses and collateralization ratios function spotOracles(bytes6 baseId, bytes6 ilkId) external returns (DataTypes.SpotOracle memory); /// @dev Create a new vault, linked to a series (and therefore underlying) and up to 5 collateral types function build( address owner, bytes12 vaultId, bytes6 seriesId, bytes6 ilkId ) external returns (DataTypes.Vault memory); /// @dev Destroy an empty vault. Used to recover gas costs. function destroy(bytes12 vault) external; /// @dev Change a vault series and/or collateral types. function tweak( bytes12 vaultId, bytes6 seriesId, bytes6 ilkId ) external returns (DataTypes.Vault memory); /// @dev Give a vault to another user. function give(bytes12 vaultId, address receiver) external returns (DataTypes.Vault memory); /// @dev Move collateral and debt between vaults. function stir( bytes12 from, bytes12 to, uint128 ink, uint128 art ) external returns (DataTypes.Balances memory, DataTypes.Balances memory); /// @dev Manipulate a vault debt and collateral. function pour( bytes12 vaultId, int128 ink, int128 art ) external returns (DataTypes.Balances memory); /// @dev Change series and debt of a vault. /// The module calling this function also needs to buy underlying in the pool for the new series, and sell it in pool for the old series. function roll( bytes12 vaultId, bytes6 seriesId, int128 art ) external returns (DataTypes.Vault memory, DataTypes.Balances memory); /// @dev Reduce debt and collateral from a vault, ignoring collateralization checks. function slurp( bytes12 vaultId, uint128 ink, uint128 art ) external returns (DataTypes.Balances memory); // ==== Helpers ==== /// @dev Convert a debt amount for a series from base to fyToken terms. /// @notice Think about rounding if using, since we are dividing. function debtFromBase(bytes6 seriesId, uint128 base) external returns (uint128 art); /// @dev Convert a debt amount for a series from fyToken to base terms function debtToBase(bytes6 seriesId, uint128 art) external returns (uint128 base); // ==== Accounting ==== /// @dev Record the borrowing rate at maturity for a series function mature(bytes6 seriesId) external; /// @dev Retrieve the rate accrual since maturity, maturing if necessary. function accrual(bytes6 seriesId) external returns (uint256); /// @dev Return the collateralization level of a vault. It will be negative if undercollateralized. function level(bytes12 vaultId) external returns (int256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IJoin.sol"; import "./ICauldron.sol"; interface ILadle { function joins(bytes6) external view returns (IJoin); function pools(bytes6) external returns (address); 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 payable; function serve( bytes12 vaultId, address to, uint128 ink, uint128 base, uint128 max ) external payable returns (uint128 art); function close( bytes12 vaultId, address to, int128 ink, int128 art ) external; }
// SPDX-License-Identifier: MIT 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); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.6; import "@yield-protocol/yieldspace-interfaces/IPool.sol"; import "../YieldMath.sol"; library YieldMathExtensions { /// @dev Calculate the invariant for this pool 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() ); } /// @dev max amount of fyTokens that can be bought from the pool 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; } /// @dev max amount of fyTokens that can be sold into the pool 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; } /// @dev max amount of Base that can be sold to the pool 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; } /// @dev max amount of Base that can be bought from the pool 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; } }
// SPDX-License-Identifier: MIT // Taken from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/IERC20Metadata.sol pragma solidity ^0.8.0; import "./IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; library AddressStringUtil { // converts an address to the uppercase hex string, extracting only len bytes (up to 20, multiple of 2) 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); } // hi and lo are only 4 bits and between 0 and 16 // this method converts those values to the unicode/ascii code point for the hex representation // uses upper case for the characters function char(uint8 b) private pure returns (bytes1 c) { if (b < 10) { return bytes1(b + 0x30); } else { return bytes1(b + 0x37); } } }
// SPDX-License-Identifier: MIT // Taken from https://github.com/sushiswap/BoringSolidity/blob/441e51c0544cf2451e6116fe00515e71d7c42e2c/contracts/BoringBatchable.sol pragma solidity >=0.6.0; library RevertMsgExtractor { /// @dev Helper function to extract a useful revert message from a failed call. /// If the returned data is malformed or not correctly abi encoded then this call can fail itself. function getRevertMsg(bytes memory returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (returnData.length < 68) return "Transaction reverted silently"; assembly { // Slice the sighash. returnData := add(returnData, 0x04) } return abi.decode(returnData, (string)); // All that remains is the revert string } }
// SPDX-License-Identifier: MIT // Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/53516bc555a454862470e7860a9b5254db4d00f5/contracts/token/ERC20/ERC20Permit.sol pragma solidity ^0.8.0; import "./ERC20.sol"; import "./IERC2612.sol"; /** * @dev Extension of {ERC20} that allows token holders to use their tokens * without sending any transactions by setting {IERC20-allowance} with a * signature using the {permit} method, and then spend them via * {IERC20-transferFrom}. * * The {permit} signature mechanism conforms to the {IERC2612} interface. */ 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); } /// @dev Calculate the DOMAIN_SEPARATOR. 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) ) ); } /// @dev Return the DOMAIN_SEPARATOR. function DOMAIN_SEPARATOR() external view returns (bytes32) { return block.chainid == deploymentChainId ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(block.chainid); } /// @dev Setting the version as a function so that it can be overriden function version() public pure virtual returns(string memory) { return "1"; } /** * @dev See {IERC2612-permit}. * * In cases where the free option is not a concern, deadline can simply be * set to uint(-1), so it should be seen as an optional parameter */ 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); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; library CastU256U128 { /// @dev Safely cast an uint256 to an uint128 function u128(uint256 x) internal pure returns (uint128 y) { require (x <= type(uint128).max, "Cast overflow"); y = uint128(x); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; library CastU256U32 { /// @dev Safely cast an uint256 to an u32 function u32(uint256 x) internal pure returns (uint32 y) { require (x <= type(uint32).max, "Cast overflow"); y = uint32(x); } }
// SPDX-License-Identifier: MIT // Inspired on token.sol from DappHub. Natspec adpated from OpenZeppelin. pragma solidity ^0.8.0; import "./IERC20Metadata.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Calls to {transferFrom} do not check for allowance if the caller is the owner * of the funds. This allows to reduce the number of approvals that are necessary. * * Finally, {transferFrom} does not decrease the allowance if it is set to * type(uint256).max. This reduces the gas costs without any likely impact. */ 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; /** * @dev Sets the values for {name}, {symbol} and {decimals}. */ constructor(string memory name_, string memory symbol_, uint8 decimals_) { name = name_; symbol = symbol_; decimals = decimals_; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() external view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address guy) external view virtual override returns (uint256) { return _balanceOf[guy]; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) external view virtual override returns (uint256) { return _allowance[owner][spender]; } /** * @dev See {IERC20-approve}. */ function approve(address spender, uint wad) external virtual override returns (bool) { return _setAllowance(msg.sender, spender, wad); } /** * @dev See {IERC20-transfer}. * * Requirements: * * - the caller must have a balance of at least `wad`. */ function transfer(address dst, uint wad) external virtual override returns (bool) { return _transfer(msg.sender, dst, wad); } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `src` must have a balance of at least `wad`. * - the caller is not `src`, it must have allowance for ``src``'s tokens of at least * `wad`. */ /// if_succeeds {:msg "TransferFrom - decrease allowance"} msg.sender != src ==> old(_allowance[src][msg.sender]) >= wad; function transferFrom(address src, address dst, uint wad) external virtual override returns (bool) { _decreaseAllowance(src, wad); return _transfer(src, dst, wad); } /** * @dev Moves tokens `wad` from `src` to `dst`. * * Emits a {Transfer} event. * * Requirements: * * - `src` must have a balance of at least `amount`. */ /// if_succeeds {:msg "Transfer - src decrease"} old(_balanceOf[src]) >= _balanceOf[src]; /// if_succeeds {:msg "Transfer - dst increase"} _balanceOf[dst] >= old(_balanceOf[dst]); /// if_succeeds {:msg "Transfer - supply"} old(_balanceOf[src]) + old(_balanceOf[dst]) == _balanceOf[src] + _balanceOf[dst]; 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; } /** * @dev Sets the allowance granted to `spender` by `owner`. * * Emits an {Approval} event indicating the updated allowance. */ function _setAllowance(address owner, address spender, uint wad) internal virtual returns (bool) { _allowance[owner][spender] = wad; emit Approval(owner, spender, wad); return true; } /** * @dev Decreases the allowance granted to the caller by `src`, unless src == msg.sender or _allowance[src][msg.sender] == MAX * * Emits an {Approval} event indicating the updated allowance, if the allowance is updated. * * Requirements: * * - `spender` must have allowance for the caller of at least * `wad`, unless src == msg.sender */ /// if_succeeds {:msg "Decrease allowance - underflow"} old(_allowance[src][msg.sender]) <= _allowance[src][msg.sender]; 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; } /** @dev Creates `wad` tokens and assigns them to `dst`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. */ /// if_succeeds {:msg "Mint - balance overflow"} old(_balanceOf[dst]) >= _balanceOf[dst]; /// if_succeeds {:msg "Mint - supply overflow"} old(_totalSupply) >= _totalSupply; 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; } /** * @dev Destroys `wad` tokens from `src`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `src` must have at least `wad` tokens. */ /// if_succeeds {:msg "Burn - balance underflow"} old(_balanceOf[src]) <= _balanceOf[src]; /// if_succeeds {:msg "Burn - supply underflow"} old(_totalSupply) <= _totalSupply; 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; } }
// SPDX-License-Identifier: MIT // Code adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/ pragma solidity ^0.8.0; /** * @dev Interface of the ERC2612 standard as defined in the EIP. * * Adds the {permit} method, which can be used to change one's * {IERC20-allowance} without having to send a transaction, by signing a * message. This allows users to spend tokens without having to hold Ether. * * See https://eips.ethereum.org/EIPS/eip-2612. */ interface IERC2612 { /** * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens, * given `owner`'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /** * @dev Returns the current ERC2612 nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@yield-protocol/utils-v2/contracts/token/IERC20.sol"; interface IFYToken is IERC20 { /// @dev Asset that is returned on redemption. function underlying() external view returns (address); /// @dev Unix time at which redemption of fyToken for underlying are possible function maturity() external view returns (uint256); /// @dev Record price data at maturity function mature() external; /// @dev Mint fyToken providing an equal amount of underlying to the protocol function mintWithUnderlying(address to, uint256 amount) external; /// @dev Burn fyToken after maturity for an amount of underlying. function redeem(address to, uint256 amount) external returns (uint256); /// @dev Mint fyToken. /// This function can only be called by other Yield contracts, not users directly. /// @param to Wallet to mint the fyToken in. /// @param fyTokenAmount Amount of fyToken to mint. function mint(address to, uint256 fyTokenAmount) external; /// @dev Burn fyToken. /// This function can only be called by other Yield contracts, not users directly. /// @param from Wallet to burn the fyToken from. /// @param fyTokenAmount Amount of fyToken to burn. function burn(address from, uint256 fyTokenAmount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IOracle { /** * @notice Doesn't refresh the price, but returns the latest value available without doing any transactional operations: * @return value in wei */ function peek( bytes32 base, bytes32 quote, uint256 amount ) external view returns (uint256 value, uint256 updateTime); /** * @notice Does whatever work or queries will yield the most up-to-date price, and returns it. * @return value in wei */ function get( bytes32 base, bytes32 quote, uint256 amount ) external returns (uint256 value, uint256 updateTime); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@yield-protocol/utils-v2/contracts/token/IERC20.sol"; interface IJoin { /// @dev asset managed by this contract function asset() external view returns (address); /// @dev Add tokens to this contract. function join(address user, uint128 wad) external returns (uint128); /// @dev Remove tokens to this contract. function exit(address user, uint128 wad) external returns (uint128); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.6; import "./Math64x64.sol"; library Exp64x64 { /** * Raise given number x into power specified as a simple fraction y/z and then * multiply the result by the normalization factor 2^(128 * (1 - y/z)). * Revert if z is zero, or if both x and y are zeros. * * @param x number to raise into given power y/z * @param y numerator of the power to raise x into * @param z denominator of the power to raise x into * @return x raised into power y/z and then multiplied by 2^(128 * (1 - y/z)) */ 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)); } } } /** * Calculate base 2 logarithm of an unsigned 128-bit integer number. Revert * in case x is zero. * * @param x number to calculate base 2 logarithm of * @return base 2 logarithm of x, multiplied by 2^121 */ 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;} /* b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x1000;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x800;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x400;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x200;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x100;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x80;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x40;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x20;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x10;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x8;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x4;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) {b >>= 1; l |= 0x2;} b = b * b >> 127; if(b >= 0x100000000000000000000000000000000) l |= 0x1; */ return uint128(l); } } /** * Calculate 2 raised into given power. * * @param x power to raise 2 into, multiplied by 2^121 * @return 2 raised into given power */ 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; /* if(x & 0x8000000000000000 > 0) r = r * 0x80000000000000162e42fefa39ef3765 >> 127; if(x & 0x4000000000000000 > 0) r = r * 0x800000000000000b17217f7d1cf79b37 >> 127; if(x & 0x2000000000000000 > 0) r = r * 0x80000000000000058b90bfbe8e7bcd7d >> 127; if(x & 0x1000000000000000 > 0) r = r * 0x8000000000000002c5c85fdf473de6b6 >> 127; if(x & 0x800000000000000 > 0) r = r * 0x800000000000000162e42fefa39ef359 >> 127; if(x & 0x400000000000000 > 0) r = r * 0x8000000000000000b17217f7d1cf79ac >> 127; if(x & 0x200000000000000 > 0) r = r * 0x800000000000000058b90bfbe8e7bcd6 >> 127; if(x & 0x100000000000000 > 0) r = r * 0x80000000000000002c5c85fdf473de6a >> 127; if(x & 0x80000000000000 > 0) r = r * 0x8000000000000000162e42fefa39ef35 >> 127; if(x & 0x40000000000000 > 0) r = r * 0x80000000000000000b17217f7d1cf79a >> 127; if(x & 0x20000000000000 > 0) r = r * 0x8000000000000000058b90bfbe8e7bcd >> 127; if(x & 0x10000000000000 > 0) r = r * 0x800000000000000002c5c85fdf473de6 >> 127; if(x & 0x8000000000000 > 0) r = r * 0x80000000000000000162e42fefa39ef3 >> 127; if(x & 0x4000000000000 > 0) r = r * 0x800000000000000000b17217f7d1cf79 >> 127; if(x & 0x2000000000000 > 0) r = r * 0x80000000000000000058b90bfbe8e7bc >> 127; if(x & 0x1000000000000 > 0) r = r * 0x8000000000000000002c5c85fdf473de >> 127; if(x & 0x800000000000 > 0) r = r * 0x800000000000000000162e42fefa39ef >> 127; if(x & 0x400000000000 > 0) r = r * 0x8000000000000000000b17217f7d1cf7 >> 127; if(x & 0x200000000000 > 0) r = r * 0x800000000000000000058b90bfbe8e7b >> 127; if(x & 0x100000000000 > 0) r = r * 0x80000000000000000002c5c85fdf473d >> 127; if(x & 0x80000000000 > 0) r = r * 0x8000000000000000000162e42fefa39e >> 127; if(x & 0x40000000000 > 0) r = r * 0x80000000000000000000b17217f7d1cf >> 127; if(x & 0x20000000000 > 0) r = r * 0x8000000000000000000058b90bfbe8e7 >> 127; if(x & 0x10000000000 > 0) r = r * 0x800000000000000000002c5c85fdf473 >> 127; if(x & 0x8000000000 > 0) r = r * 0x80000000000000000000162e42fefa39 >> 127; if(x & 0x4000000000 > 0) r = r * 0x800000000000000000000b17217f7d1c >> 127; if(x & 0x2000000000 > 0) r = r * 0x80000000000000000000058b90bfbe8e >> 127; if(x & 0x1000000000 > 0) r = r * 0x8000000000000000000002c5c85fdf47 >> 127; if(x & 0x800000000 > 0) r = r * 0x800000000000000000000162e42fefa3 >> 127; if(x & 0x400000000 > 0) r = r * 0x8000000000000000000000b17217f7d1 >> 127; if(x & 0x200000000 > 0) r = r * 0x800000000000000000000058b90bfbe8 >> 127; if(x & 0x100000000 > 0) r = r * 0x80000000000000000000002c5c85fdf4 >> 127; if(x & 0x80000000 > 0) r = r * 0x8000000000000000000000162e42fefa >> 127; if(x & 0x40000000 > 0) r = r * 0x80000000000000000000000b17217f7d >> 127; if(x & 0x20000000 > 0) r = r * 0x8000000000000000000000058b90bfbe >> 127; if(x & 0x10000000 > 0) r = r * 0x800000000000000000000002c5c85fdf >> 127; if(x & 0x8000000 > 0) r = r * 0x80000000000000000000000162e42fef >> 127; if(x & 0x4000000 > 0) r = r * 0x800000000000000000000000b17217f7 >> 127; if(x & 0x2000000 > 0) r = r * 0x80000000000000000000000058b90bfb >> 127; if(x & 0x1000000 > 0) r = r * 0x8000000000000000000000002c5c85fd >> 127; if(x & 0x800000 > 0) r = r * 0x800000000000000000000000162e42fe >> 127; if(x & 0x400000 > 0) r = r * 0x8000000000000000000000000b17217f >> 127; if(x & 0x200000 > 0) r = r * 0x800000000000000000000000058b90bf >> 127; if(x & 0x100000 > 0) r = r * 0x80000000000000000000000002c5c85f >> 127; if(x & 0x80000 > 0) r = r * 0x8000000000000000000000000162e42f >> 127; if(x & 0x40000 > 0) r = r * 0x80000000000000000000000000b17217 >> 127; if(x & 0x20000 > 0) r = r * 0x8000000000000000000000000058b90b >> 127; if(x & 0x10000 > 0) r = r * 0x800000000000000000000000002c5c85 >> 127; if(x & 0x8000 > 0) r = r * 0x80000000000000000000000000162e42 >> 127; if(x & 0x4000 > 0) r = r * 0x800000000000000000000000000b1721 >> 127; if(x & 0x2000 > 0) r = r * 0x80000000000000000000000000058b90 >> 127; if(x & 0x1000 > 0) r = r * 0x8000000000000000000000000002c5c8 >> 127; if(x & 0x800 > 0) r = r * 0x800000000000000000000000000162e4 >> 127; if(x & 0x400 > 0) r = r * 0x8000000000000000000000000000b172 >> 127; if(x & 0x200 > 0) r = r * 0x800000000000000000000000000058b9 >> 127; if(x & 0x100 > 0) r = r * 0x80000000000000000000000000002c5c >> 127; if(x & 0x80 > 0) r = r * 0x8000000000000000000000000000162e >> 127; if(x & 0x40 > 0) r = r * 0x80000000000000000000000000000b17 >> 127; if(x & 0x20 > 0) r = r * 0x8000000000000000000000000000058b >> 127; if(x & 0x10 > 0) r = r * 0x800000000000000000000000000002c5 >> 127; if(x & 0x8 > 0) r = r * 0x80000000000000000000000000000162 >> 127; if(x & 0x4 > 0) r = r * 0x800000000000000000000000000000b1 >> 127; if(x & 0x2 > 0) r = r * 0x80000000000000000000000000000058 >> 127; if(x & 0x1 > 0) r = r * 0x8000000000000000000000000000002c >> 127; */ r >>= 127 -(x >> 121); return uint128(r); } } } /** * Ethereum smart contract library implementing Yield Math model. */ 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; // In 64.64 uint128 public constant TWO = 0x20000000000000000; // In 64.64 uint256 public constant MAX = type(uint128).max; // Used for overflow checks uint256 public constant VAR = 1e12; // The logarithm math used is not precise to the wei, but can deviate up to 1e12 from the real value. /** * Calculate a YieldSpace pool invariant according to the whitepaper */ function invariant(uint128 baseReserves, uint128 fyTokenReserves, uint256 totalSupply, uint128 timeTillMaturity, int128 ts) public pure returns(uint128) { if (totalSupply == 0) return 0; unchecked { // a = (1 - ts * timeTillMaturity) 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"); // We multiply the dividend by 1e18 to get a fixed point number with 18 decimals uint256 result = uint256(uint128(sum).pow(ONE, uint128(a))) * 1e18 / totalSupply; require (result < MAX, "YieldMath: Result overflow"); return uint128(result); } } /** * Calculate the amount of fyToken a user would get for given amount of Base. * https://www.desmos.com/calculator/5nf2xuy6yb * @param baseReserves base reserves amount * @param fyTokenReserves fyToken reserves amount * @param baseAmount base amount to be traded * @param timeTillMaturity time till maturity in seconds * @param ts time till maturity coefficient, multiplied by 2^64 * @param g fee coefficient, multiplied by 2^64 * @return the amount of fyToken a user would get for given amount of Base */ 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); // za = baseReserves ** a uint256 za = baseReserves.pow(a, ONE); // ya = fyTokenReserves ** a uint256 ya = fyTokenReserves.pow(a, ONE); // zx = baseReserves + baseAmount uint256 zx = uint256(baseReserves) + uint256(baseAmount); require(zx <= MAX, "YieldMath: Too much base in"); // zxa = zx ** a uint256 zxa = uint128(zx).pow(a, ONE); // sum = za + ya - zxa uint256 sum = za + ya - zxa; // z < MAX, y < MAX, a < 1. It can only underflow, not overflow. require(sum <= MAX, "YieldMath: Insufficient fyToken reserves"); // result = fyTokenReserves - (sum ** (1/a)) uint256 result = uint256(fyTokenReserves) - uint256(uint128(sum).pow(ONE, a)); require(result <= MAX, "YieldMath: Rounding induced error"); result = result > VAR ? result - VAR : 0; // Subtract error guard, flooring the result at zero return uint128(result); } } /** * Calculate the amount of base a user would get for certain amount of fyToken. * https://www.desmos.com/calculator/6jlrre7ybt * @param baseReserves base reserves amount * @param fyTokenReserves fyToken reserves amount * @param fyTokenAmount fyToken amount to be traded * @param timeTillMaturity time till maturity in seconds * @param ts time till maturity coefficient, multiplied by 2^64 * @param g fee coefficient, multiplied by 2^64 * @return the amount of Base a user would get for given amount of fyToken */ 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); // za = baseReserves ** a uint256 za = baseReserves.pow(a, ONE); // ya = fyTokenReserves ** a uint256 ya = fyTokenReserves.pow(a, ONE); // yx = fyDayReserves + fyTokenAmount uint256 yx = uint256(fyTokenReserves) + uint256(fyTokenAmount); require(yx <= MAX, "YieldMath: Too much fyToken in"); // yxa = yx ** a uint256 yxa = uint128(yx).pow(a, ONE); // sum = za + ya - yxa uint256 sum = za + ya - yxa; // z < MAX, y < MAX, a < 1. It can only underflow, not overflow. require(sum <= MAX, "YieldMath: Insufficient base reserves"); // result = baseReserves - (sum ** (1/a)) uint256 result = uint256(baseReserves) - uint256(uint128(sum).pow(ONE, a)); require(result <= MAX, "YieldMath: Rounding induced error"); result = result > VAR ? result - VAR : 0; // Subtract error guard, flooring the result at zero return uint128(result); } } /** * Calculate the amount of fyToken a user could sell for given amount of Base. * https://www.desmos.com/calculator/0rgnmtckvy * @param baseReserves base reserves amount * @param fyTokenReserves fyToken reserves amount * @param baseAmount Base amount to be traded * @param timeTillMaturity time till maturity in seconds * @param ts time till maturity coefficient, multiplied by 2^64 * @param g fee coefficient, multiplied by 2^64 * @return the amount of fyToken a user could sell for given amount of Base */ 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); // za = baseReserves ** a uint256 za = baseReserves.pow(a, ONE); // ya = fyTokenReserves ** a uint256 ya = fyTokenReserves.pow(a, ONE); // zx = baseReserves - baseAmount uint256 zx = uint256(baseReserves) - uint256(baseAmount); require(zx <= MAX, "YieldMath: Too much base out"); // zxa = zx ** a uint256 zxa = uint128(zx).pow(a, ONE); // sum = za + ya - zxa uint256 sum = za + ya - zxa; // z < MAX, y < MAX, a < 1. It can only underflow, not overflow. require(sum <= MAX, "YieldMath: Resulting fyToken reserves too high"); // result = (sum ** (1/a)) - fyTokenReserves uint256 result = uint256(uint128(sum).pow(ONE, a)) - uint256(fyTokenReserves); require(result <= MAX, "YieldMath: Rounding induced error"); result = result < MAX - VAR ? result + VAR : MAX; // Add error guard, ceiling the result at max return uint128(result); } } /** * Calculate the amount of base a user would have to pay for certain amount of fyToken. * https://www.desmos.com/calculator/ws5oqj8x5i * @param baseReserves Base reserves amount * @param fyTokenReserves fyToken reserves amount * @param fyTokenAmount fyToken amount to be traded * @param timeTillMaturity time till maturity in seconds * @param ts time till maturity coefficient, multiplied by 2^64 * @param g fee coefficient, multiplied by 2^64 * @return the amount of base a user would have to pay for given amount of * fyToken */ 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); // za = baseReserves ** a uint256 za = baseReserves.pow(a, ONE); // ya = fyTokenReserves ** a uint256 ya = fyTokenReserves.pow(a, ONE); // yx = baseReserves - baseAmount uint256 yx = uint256(fyTokenReserves) - uint256(fyTokenAmount); require(yx <= MAX, "YieldMath: Too much fyToken out"); // yxa = yx ** a uint256 yxa = uint128(yx).pow(a, ONE); // sum = za + ya - yxa uint256 sum = za + ya - yxa; // z < MAX, y < MAX, a < 1. It can only underflow, not overflow. require(sum <= MAX, "YieldMath: Resulting base reserves too high"); // result = (sum ** (1/a)) - baseReserves uint256 result = uint256(uint128(sum).pow(ONE, a)) - uint256(baseReserves); require(result <= MAX, "YieldMath: Rounding induced error"); result = result < MAX - VAR ? result + VAR : MAX; // Add error guard, ceiling the result at max return uint128(result); } } /** * Calculate the max amount of fyTokens that can be bought from the pool without making the interest rate negative. * See section 6.3 of the YieldSpace White paper * @param baseReserves Base reserves amount * @param fyTokenReserves fyToken reserves amount * @param timeTillMaturity time till maturity in seconds * @param ts time till maturity coefficient, multiplied by 2^64 * @param g fee coefficient, multiplied by 2^64 * @return max amount of fyTokens that can be bought from the pool */ 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); // xa = baseReserves ** a uint128 xa = baseReserves.pow(a, ONE); // ya = fyTokenReserves ** a 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; // Add error guard, ceiling the result at max return uint128(inaccessible) > fyTokenReserves ? 0 : fyTokenReserves - uint128(inaccessible); } } /** * Calculate the max amount of fyTokens that can be sold to into the pool. * @param baseReserves Base reserves amount * @param fyTokenReserves fyToken reserves amount * @param timeTillMaturity time till maturity in seconds * @param ts time till maturity coefficient, multiplied by 2^64 * @param g fee coefficient, multiplied by 2^64 * @return max amount of fyTokens that can be sold to into the pool */ function maxFYTokenIn( uint128 baseReserves, uint128 fyTokenReserves, uint128 timeTillMaturity, int128 ts, int128 g) public pure returns(uint128) { unchecked { uint128 b = _computeB(timeTillMaturity, ts, g); // xa = baseReserves ** a uint128 xa = baseReserves.pow(b, ONE); // ya = fyTokenReserves ** a 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; // Subtract error guard, flooring the result at zero return uint128(result); } } /** * Calculate the max amount of base that can be sold to into the pool without making the interest rate negative. * @param baseReserves Base reserves amount * @param fyTokenReserves fyToken reserves amount * @param timeTillMaturity time till maturity in seconds * @param ts time till maturity coefficient, multiplied by 2^64 * @param g fee coefficient, multiplied by 2^64 * @return max amount of base that can be sold to into the pool */ 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; } /** * Calculate the max amount of base that can be bought from the pool. * @param baseReserves Base reserves amount * @param fyTokenReserves fyToken reserves amount * @param timeTillMaturity time till maturity in seconds * @param ts time till maturity coefficient, multiplied by 2^64 * @param g fee coefficient, multiplied by 2^64 * @return max amount of base that can be bought from the pool */ 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 { // t = ts * timeTillMaturity int128 t = ts.mul(timeTillMaturity.fromUInt()); require(t >= 0, "YieldMath: t must be positive"); // Meaning neither T or ts can be negative // a = (1 - gt) 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 { // t = ts * timeTillMaturity int128 t = ts.mul(timeTillMaturity.fromUInt()); require(t >= 0, "YieldMath: t must be positive"); // Meaning neither T or ts can be negative // b = (1 - t/g) 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); } } }
// SPDX-License-Identifier: BUSL-1.1 /* * Math 64.64 Smart Contract Library. Copyright © 2019 by Consulting. * Author: Mikhail Vladimirov <[email protected]> */ pragma solidity 0.8.6; /** * Smart contract library of mathematical functions operating with signed * 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is * basically a simple fraction whose numerator is signed 128-bit integer and * denominator is 2^64. As long as denominator is always the same, there is no * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are * represented by int128 type holding only the numerator. */ library Math64x64 { /* * Minimum value signed 64.64-bit fixed point number may have. */ int128 private constant MIN_64x64 = -0x80000000000000000000000000000000; /* * Maximum value signed 64.64-bit fixed point number may have. */ int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; /** * Convert signed 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromInt (int256 x) internal pure returns (int128) { unchecked { require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF); return int128 (x << 64); } } /** * Convert signed 64.64 fixed point number into signed 64-bit integer number * rounding down. * * @param x signed 64.64-bit fixed point number * @return signed 64-bit integer number */ function toInt (int128 x) internal pure returns (int64) { unchecked { return int64 (x >> 64); } } /** * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromUInt (uint256 x) internal pure returns (int128) { unchecked { require (x <= 0x7FFFFFFFFFFFFFFF); return int128 (int256 (x << 64)); } } /** * Convert signed 64.64 fixed point number into unsigned 64-bit integer * number rounding down. Revert on underflow. * * @param x signed 64.64-bit fixed point number * @return unsigned 64-bit integer number */ function toUInt (int128 x) internal pure returns (uint64) { unchecked { require (x >= 0); return uint64 (uint128 (x >> 64)); } } /** * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point * number rounding down. Revert on overflow. * * @param x signed 128.128-bin fixed point number * @return signed 64.64-bit fixed point number */ function from128x128 (int256 x) internal pure returns (int128) { unchecked { int256 result = x >> 64; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Convert signed 64.64 fixed point number into signed 128.128 fixed point * number. * * @param x signed 64.64-bit fixed point number * @return signed 128.128 fixed point number */ function to128x128 (int128 x) internal pure returns (int256) { unchecked { return int256 (x) << 64; } } /** * Calculate x + y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ 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); } } /** * Calculate x - y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ 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); } } /** * Calculate x * y rounding down. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ 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); } } /** * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point * number and y is signed 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y signed 256-bit integer number * @return signed 256-bit integer number */ 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; // We rely on overflow behavior here negativeResult = !negativeResult; } uint256 absoluteResult = mulu (x, uint256 (y)); if (negativeResult) { require (absoluteResult <= 0x8000000000000000000000000000000000000000000000000000000000000000); return -int256 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int256 (absoluteResult); } } } } /** * Calculate x * y rounding down, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y unsigned 256-bit integer number * @return unsigned 256-bit integer number */ 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; } } /** * Calculate x / y rounding towards zero. Revert on overflow or when y is * zero. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ 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); } } /** * Calculate x / y rounding towards zero, where x and y are signed 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x signed 256-bit integer number * @param y signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function divi (int256 x, int256 y) internal pure returns (int128) { unchecked { require (y != 0); bool negativeResult = false; if (x < 0) { x = -x; // We rely on overflow behavior here negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint128 absoluteResult = divuu (uint256 (x), uint256 (y)); if (negativeResult) { require (absoluteResult <= 0x80000000000000000000000000000000); return -int128 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int128 (absoluteResult); // We rely on overflow behavior here } } } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ 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); } } /** * Calculate -x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function neg (int128 x) internal pure returns (int128) { unchecked { require (x != MIN_64x64); return -x; } } /** * Calculate |x|. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function abs (int128 x) internal pure returns (int128) { unchecked { require (x != MIN_64x64); return x < 0 ? -x : x; } } /** * Calculate 1 / x rounding towards zero. Revert on overflow or when x is * zero. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ 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); } } /** * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function avg (int128 x, int128 y) internal pure returns (int128) { unchecked { return int128 ((int256 (x) + int256 (y)) >> 1); } } /** * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down. * Revert on overflow or in case x * y is negative. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ 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))); } } /** * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y uint256 value * @return signed 64.64-bit fixed point number */ 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); } } /** * Calculate sqrt (x) rounding down. Revert if x < 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sqrt (int128 x) internal pure returns (int128) { unchecked { require (x >= 0); return int128 (sqrtu (uint256 (int256 (x)) << 64)); } } /** * Calculate binary logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ 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; // No need to shift xc anymore 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); } } /** * Calculate natural logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function ln (int128 x) internal pure returns (int128) { unchecked { require (x > 0); return int128 (int256 ( uint256 (int256 (log_2 (x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128)); } } /** * Calculate binary exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp_2 (int128 x) internal pure returns (int128) { unchecked { require (x < 0x400000000000000000); // Overflow if (x < -0x400000000000000000) return 0; // Underflow 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)); } } /** * Calculate natural exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp (int128 x) internal pure returns (int128) { unchecked { require (x < 0x400000000000000000); // Overflow if (x < -0x400000000000000000) return 0; // Underflow return exp_2 ( int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128)); } } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return unsigned 64.64-bit fixed point number */ 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; // No need to shift xc anymore 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; // We rely on overflow behavior here lo = hi << 128; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here assert (xh == hi >> 128); result += xl / y; } require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return uint128 (result); } } /** * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer * number. * * @param x unsigned 256-bit integer number * @return unsigned 128-bit integer number */ 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; // Seven iterations should be enough uint256 r1 = x / r; return uint128 (r < r1 ? r : r1); } } } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": { "@yield-protocol/utils-v2/contracts/token/SafeERC20Namer.sol": { "SafeERC20Namer": "0x39bb9cBe0221D769E30bD08d185842065BcE1706" }, "@yield-protocol/yieldspace-v2/contracts/extensions/YieldMathExtensions.sol": { "YieldMathExtensions": "0xdc3758330939a0253f30083a23e8843778348991" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
6101406040526003610100819052623f3f3f60e81b6101209081526200002991600491906200069b565b50604080518082019091526003808252623f3f3f60e81b602090920191825262000056916005916200069b565b506006805460ff191660121790557f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c96080523480156200009557600080fd5b5060405162004a4e38038062004a4e833981016040819052620000b8916200081f565b6040516323b95ceb60e21b81526001600160a01b0383166004820152859085907339bb9cbe0221d769e30bd08d185842065bce170690638ee573ac9060240160206040518083038186803b1580156200011057600080fd5b505af415801562000125573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014b9190620008d7565b8282828282826200015e600033620004af565b620001726001600160e01b03198062000547565b8251620001879060049060208601906200069b565b5081516200019d9060059060208501906200069b565b506006805460ff191660ff9290921691909117905550504660c0819052620001c590620005e5565b60a08181525050505050505050816001600160a01b0316836001600160a01b03166397ff6a046040518163ffffffff1660e01b815260040160206040518083038186803b1580156200021657600080fd5b505afa1580156200022b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002519190620007f8565b604051630cdf468960e11b81526001600160d01b0319841660048201526001600160a01b0391909116906319be8d129060240160206040518083038186803b1580156200029d57600080fd5b505afa158015620002b2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002d89190620007f8565b6001600160a01b031614620003275760405162461bcd60e51b8152602060048201526011602482015270135a5cdb585d18da19590818985cd95259607a1b604482015260640160405180910390fd5b606082901b6001600160601b03191660e052600c805465ffffffffffff191660d083901c1790556040516330705b1b60e11b81526001600160d01b0319821660048201526001600160a01b038416906360e0b6369060240160206040518083038186803b1580156200039857600080fd5b505afa158015620003ad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003d39190620007f8565b600c8054600160301b600160d01b03191666010000000000006001600160a01b0393841602179055600d80546001600160a01b0319169185169182179055604080516325ffda8160e21b815290516397ff6a0491600480820192602092909190829003018186803b1580156200044857600080fd5b505afa1580156200045d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004839190620007f8565b600e80546001600160a01b0319166001600160a01b03929092169190911790555062000a0c9350505050565b6001600160e01b031982166000908152602081815260408083206001600160a01b038516845290915290205460ff1662000543576001600160e01b031982166000818152602081815260408083206001600160a01b0386168085529252808320805460ff1916600117905551339391927fe6231789d19137da31d0550f4ba9ee379020a8cfb64cb79bf1790c996d2e616591a45b5050565b6001600160e01b0319811662000579836001600160e01b03191660009081526020819052604090206001015460e01b90565b6001600160e01b0319161462000543576001600160e01b0319828116600081815260208190526040808220600101805463ffffffff191660e087901c17905551928416927fd348e2220a50b4500ec353f6e802d2f14dd1b5d6786148fd1bbcc570bf92d4739190a35050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6004604051620006199190620008fc565b60408051918290038220828201825260018352603160f81b602093840152815180840194909452838201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606084015260808301949094523060a0808401919091528451808403909101815260c09092019093528051920191909120919050565b828054620006a990620009a0565b90600052602060002090601f016020900481019282620006cd576000855562000718565b82601f10620006e857805160ff191683800117855562000718565b8280016001018555821562000718579182015b8281111562000718578251825591602001919060010190620006fb565b50620007269291506200072a565b5090565b5b808211156200072657600081556001016200072b565b600082601f8301126200075357600080fd5b81516001600160401b0380821115620007705762000770620009dd565b604051601f8301601f19908116603f011681019082821181831017156200079b576200079b620009dd565b81604052838152602092508683858801011115620007b857600080fd5b600091505b83821015620007dc5785820183015181830184015290820190620007bd565b83821115620007ee5760008385830101525b9695505050505050565b6000602082840312156200080b57600080fd5b81516200081881620009f3565b9392505050565b600080600080600060a086880312156200083857600080fd5b85516001600160401b03808211156200085057600080fd5b6200085e89838a0162000741565b965060208801519150808211156200087557600080fd5b50620008848882890162000741565b94505060408601516200089781620009f3565b6060870151909350620008aa81620009f3565b60808701519092506001600160d01b031981168114620008c957600080fd5b809150509295509295909350565b600060208284031215620008ea57600080fd5b815160ff811681146200081857600080fd5b600080835481600182811c9150808316806200091957607f831692505b60208084108214156200093a57634e487b7160e01b86526022600452602486fd5b818015620009515760018114620009635762000992565b60ff1986168952848901965062000992565b60008a81526020902060005b868110156200098a5781548b8201529085019083016200096f565b505084890196505b509498975050505050505050565b600181811c90821680620009b557607f821691505b60208210811415620009d757634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811462000a0957600080fd5b50565b60805160a05160c05160e05160601c613fb162000a9d6000396000818161059f015281816112010152818161191e015281816119c60152818161222b01528181612673015281816127610152818161289f015261295e0152600081816107db01528181610e0b0152611ae8015260008181610e410152611b1d01526000818161053e0152611a5f0152613fb16000f3fe608060405234801561001057600080fd5b50600436106103735760003560e01c80637ecebe00116101d3578063cd0d009611610104578063de02cde7116100a2578063e9e5d6d01161007c578063e9e5d6d0146108f1578063effae35314610904578063f8c2b77314610917578063ffffffff1461077b57600080fd5b8063de02cde71461088a578063de320cc11461089d578063dea587b0146108b057600080fd5b8063d95edafe116100de578063d95edafe14610823578063dc3bfba914610836578063dd46e85414610849578063dd62ed3e1461085157600080fd5b8063cd0d0096146107d6578063d1af0c7d146107fd578063d505accf1461081057600080fd5b806397ff6a0411610171578063a9059cbb1161014b578063a9059cbb1461078a578063ad82110f1461079d578063ae93c1b5146107b0578063ba3573b0146107c357600080fd5b806397ff6a0414610755578063a354f39e14610768578063a4f0d7d01461077b57600080fd5b80638cc96ac5116101ad5780638cc96ac51461071d5780639326295b1461073157806394b8e38f1461073a57806395d89b411461074d57600080fd5b80637ecebe00146106d75780638737a2dc146106f757806389afcb441461070a57600080fd5b806330adf81f116102ad5780635909c12f1161024b5780636a627842116102255780636a627842146106175780636ed3e3e31461062a57806370641a361461063e57806370a08231146106ae57600080fd5b80635909c12f146103785780635ba5e9f0146105f1578063687f0e4c1461060457600080fd5b806344faded01161028757806344faded0146105875780635001f3b51461059a57806354fd4d50146105c1578063559742d9146105de57600080fd5b806330adf81f14610539578063313ce567146105605780633644e5151461057f57600080fd5b806318160ddd1161031a578063243d6585116102f4578063243d6585146104bd57806326ae2b78146104d057806328c3b85c146105095780632d42cf7d1461052f57600080fd5b806318160ddd146104855780631e83409a1461049757806323b872dd146104aa57600080fd5b80630700037d116103565780630700037d146103e8578063095ea7b31461043c57806310ab94321461045f57806316f0115b1461047257600080fd5b8015610378578063068b8a801461039e57806306fdde03146103d3575b600080fd5b610380600081565b6040516001600160e01b031990911681526020015b60405180910390f35b600c546103bb90660100000000000090046001600160a01b031681565b6040516001600160a01b039091168152602001610395565b6103db61092a565b6040516103959190613d44565b61041c6103f63660046137a4565b600b602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b03938416815292909116602083015201610395565b61044f61044a3660046138cf565b6109b8565b6040519015158152602001610395565b61044f61046d3660046139fe565b6109cc565b600f546103bb906001600160a01b031681565b6001545b604051908152602001610395565b6104896104a53660046137a4565b610a00565b61044f6104b8366004613817565b610aa5565b6011546103bb906001600160a01b031681565b6009546104ec9063ffffffff8082169164010000000090041682565b6040805163ffffffff938416815292909116602083015201610395565b600c546105169060d01b81565b6040516001600160d01b03199091168152602001610395565b610537610ac5565b005b6104897f000000000000000000000000000000000000000000000000000000000000000081565b60065461056d9060ff1681565b60405160ff9091168152602001610395565b610489610e07565b6105376105953660046139fe565b610e63565b6103bb7f000000000000000000000000000000000000000000000000000000000000000081565b6040805180820190915260018152603160f81b60208201526103db565b6105376105ec3660046139e3565b610efd565b6103806105ff3660046139e3565b610f76565b6105376106123660046139fe565b610f9d565b6104896106253660046137a4565b610fff565b60115461051690600160a01b900460d01b81565b600a54610676906001600160801b03811690600160801b810463ffffffff1690600160a01b90046bffffffffffffffffffffffff1683565b604080516001600160801b03909416845263ffffffff90921660208401526bffffffffffffffffffffffff1690820152606001610395565b6104896106bc3660046137a4565b6001600160a01b031660009081526002602052604090205490565b6104896106e53660046137a4565b60076020526000908152604090205481565b610537610705366004613a6a565b611123565b6104896107183660046137a4565b61144a565b600f5461051690600160a01b900460d01b81565b61048960125481565b600d546103bb906001600160a01b031681565b6103db611507565b600e546103bb906001600160a01b031681565b610537610776366004613c30565b611514565b6103806001600160e01b031981565b61044f6107983660046138cf565b611766565b6105376107ab3660046138fb565b611773565b6105376107be366004613a1a565b61182f565b6104896107d13660046137a4565b61189c565b6104897f000000000000000000000000000000000000000000000000000000000000000081565b6008546103bb906001600160a01b031681565b61053761081e366004613858565b6119f3565b6105376108313660046137a4565b611c7d565b6010546103bb906001600160a01b031681565b610537611e19565b61048961085f3660046137de565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b6105376108983660046139fe565b611fe6565b6105376108ab3660046137a4565b612053565b6108d96108be3660046137a4565b6013602052600090815260409020546001600160801b031681565b6040516001600160801b039091168152602001610395565b6105376108ff366004613a4d565b612163565b6105376109123660046138fb565b6123ed565b610537610925366004613be0565b61247f565b6004805461093790613e7f565b80601f016020809104026020016040519081016040528092919081815260200182805461096390613e7f565b80156109b05780601f10610985576101008083540402835291602001916109b0565b820191906000526020600020905b81548152906001019060200180831161099357829003601f168201915b505050505081565b60006109c5338484612b6c565b9392505050565b6001600160e01b031982166000908152602081815260408083206001600160a01b038516845290915281205460ff166109c5565b6000610a0a612bd5565b610a1333612dbb565b336000908152600b6020526040902080546fffffffffffffffffffffffffffffffff191690556008546001600160801b03919091169150610a5e906001600160a01b03168383612f30565b604080516001600160a01b0384168152602081018390527fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a910160405180910390a1919050565b6000610ab18483613053565b50610abd8484846130fc565b949350505050565b601060009054906101000a90046001600160a01b03166001600160a01b031663204f83f96040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1357600080fd5b505afa158015610b27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4b9190613bc7565b4263ffffffff161015610ba55760405162461bcd60e51b815260206004820152601360248201527f4f6e6c79206166746572206d617475726974790000000000000000000000000060448201526064015b60405180910390fd5b600f546010546040516370a0823160e01b81523060048201526001600160a01b03928316929091169060009083906370a082319060240160206040518083038186803b158015610bf457600080fd5b505afa158015610c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2c9190613bc7565b9050610c426001600160a01b0384168483612f30565b6040517fd7020d0a000000000000000000000000000000000000000000000000000000008152306004820181905260248201526000604482018190526000196064830152906001600160a01b0385169063d7020d0a90608401606060405180830381600087803b158015610cb557600080fd5b505af1158015610cc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ced9190613c02565b9250610d069150506001600160a01b0384168483612f30565b6040517f1e9a6950000000000000000000000000000000000000000000000000000000008152306004820152602481018290526001600160a01b03841690631e9a695090604401602060405180830381600087803b158015610d6757600080fd5b505af1158015610d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9f9190613bc7565b506040516001600160a01b03851681527ffeba534d95469be2b9f083643be5f83b8ffd5aba9b64b79f3e71e51acd5c87a29060200160405180910390a15050600f8054601080546001600160a01b03191690556001600160d01b031916905550506000601255565b60007f00000000000000000000000000000000000000000000000000000000000000004614610e3e57610e3946613125565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b81610eb5610e8d826001600160e01b03191660009081526020819052604090206001015460e01b90565b6001600160e01b03191660009081526020818152604080832033845290915290205460ff1690565b610eee5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b610ef883836131d9565b505050565b80610f27610e8d826001600160e01b03191660009081526020819052604090206001015460e01b90565b610f605760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b610f72826001600160e01b031961326d565b5050565b6001600160e01b0319811660009081526020819052604081206001015460e01b5b92915050565b6001600160a01b0381163314610ff55760405162461bcd60e51b815260206004820152601660248201527f52656e6f756e6365206f6e6c7920666f722073656c66000000000000000000006044820152606401610b9c565b610f7282826131d9565b600f546000906001600160a01b031661105a5760405162461bcd60e51b815260206004820152601160248201527f506f6f6c206e6f742073656c65637465640000000000000000000000000000006044820152606401610b9c565b601254600f546040516370a0823160e01b815230600482015260009183916001600160a01b03909116906370a082319060240160206040518083038186803b1580156110a557600080fd5b505afa1580156110b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190613bc7565b6110e79190613e1b565b905081816001546110f89190613dd4565b6111029190613dc0565b925061110e8183613da8565b60125561111b8484613309565b505050919050565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff166111855760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b816001600160a01b0316635001f3b56040518163ffffffff1660e01b815260040160206040518083038186803b1580156111be57600080fd5b505afa1580156111d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f691906137c1565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146112765760405162461bcd60e51b815260206004820152600f60248201527f4d69736d617463686564206261736500000000000000000000000000000000006044820152606401610b9c565b600e546040517f55d03e340000000000000000000000000000000000000000000000000000000081526001600160d01b0319831660048201526000916001600160a01b0316906355d03e349060240160606040518083038186803b1580156112dd57600080fd5b505afa1580156112f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113159190613b2c565b9050826001600160a01b031663dc3bfba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561135057600080fd5b505afa158015611364573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138891906137c1565b6001600160a01b031681600001516001600160a01b0316146113ec5760405162461bcd60e51b815260206004820152601360248201527f4d69736d617463686564207365726965734964000000000000000000000000006044820152606401610b9c565b601180546001600160a01b0385166001600160d01b03199182168117600160a01b60d087901c021790925560405190841691907fa0868ad381d06fdaa9677c62624fe2c7bdcfb52ff9147345f2b1b691f3f5ec7d90600090a3505050565b600f546000906001600160a01b03166114a55760405162461bcd60e51b815260206004820152601160248201527f506f6f6c206e6f742073656c65637465640000000000000000000000000000006044820152606401610b9c565b601254306000908152600260205260409020546001546114c58284613dd4565b6114cf9190613dc0565b92506114db8383613e1b565b6012556114e83082613327565b50600f54611500906001600160a01b03168585612f30565b5050919050565b6005805461093790613e7f565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff166115765760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b8163ffffffff168363ffffffff1611156115d25760405162461bcd60e51b815260206004820152600f60248201527f496e636f727265637420696e70757400000000000000000000000000000000006044820152606401610b9c565b6008546001600160a01b031661162a5760405162461bcd60e51b815260206004820152601560248201527f5265776172647320746f6b656e206e6f742073657400000000000000000000006044820152606401610b9c565b60095463ffffffff1661163c42613345565b63ffffffff16108061166b5750600954640100000000900463ffffffff1661166342613345565b63ffffffff16115b6116b75760405162461bcd60e51b815260206004820152600f60248201527f4f6e676f696e67207265776172647300000000000000000000000000000000006044820152606401610b9c565b6009805463ffffffff85811667ffffffffffffffff19909216821764010000000091861691820217909255600a80546001600160801b0316600160801b83026001600160a01b031617600160a01b6bffffffffffffffffffffffff861690810291909117909155604080519283526020830193909352918101919091527f95efd8a2a0aa591f48fd9673cf5d13c2150ca7a1fe1cbe438dd3f0ae470646639060600160405180910390a1505050565b60006109c53384846130fc565b60005b8251811015610ef8576117c1610e8d84838151811061179757611797613f0f565b60200260200101516001600160e01b03191660009081526020819052604090206001015460e01b90565b6117fa5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b61181d83828151811061180f5761180f613f0f565b6020026020010151836131d9565b8061182781613eb4565b915050611776565b81611859610e8d826001600160e01b03191660009081526020819052604090206001015460e01b90565b6118925760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b610ef8838361326d565b600f546000906001600160a01b0316156118e85760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b30600081815260026020526040908190205460015491516370a0823160e01b815260048101939093529182906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b15801561196057600080fd5b505afa158015611974573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119989190613bc7565b6119a29190613dd4565b6119ac9190613dc0565b91506119b83082613327565b506119ed6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168484612f30565b50919050565b42841015611a435760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610b9c565b6001600160a01b038716600090815260076020526040812080547f0000000000000000000000000000000000000000000000000000000000000000918a918a918a919086611a9083613eb4565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060007f00000000000000000000000000000000000000000000000000000000000000004614611b1b57611b1646613125565b611b3d565b7f00000000000000000000000000000000000000000000000000000000000000005b6040517f1901000000000000000000000000000000000000000000000000000000000000602082015260228101919091526042810183905260620160408051601f198184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015611be3573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611c195750896001600160a01b0316816001600160a01b0316145b611c655760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610b9c565b611c708a8a8a612b6c565b5050505050505050505050565b600f546001600160a01b031615611cc65760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff16611d285760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b600d80546001600160a01b0319166001600160a01b038316908117909155604080516325ffda8160e21b81529051600092916397ff6a04916004808301926020929190829003018186803b158015611d7f57600080fd5b505afa158015611d93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db791906137c1565b600e80546001600160a01b0319166001600160a01b0383811691821790925560408051928616835260208301919091529192507f2fe4e5ef899cc1bf6c10bd764667743de04f9dfe0ad51bbc956f4539b4f8a654910160405180910390a15050565b600f546001600160a01b031615611e625760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff16611ec45760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b600d54600c546040517f60e0b63600000000000000000000000000000000000000000000000000000000815260d09190911b6001600160d01b03191660048201526001600160a01b03909116906360e0b6369060240160206040518083038186803b158015611f3257600080fd5b505afa158015611f46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6a91906137c1565b600c80547fffffffffffff0000000000000000000000000000000000000000ffffffffffff1666010000000000006001600160a01b0393841681029190911791829055604051910490911681527f9261f5bf303fa2594f2b969e042420fc0125c062081305ab742561823f41c8f89060200160405180910390a1565b81612010610e8d826001600160e01b03191660009081526020819052604090206001015460e01b90565b6120495760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b610ef8838361338f565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff166120b55760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b6008546001600160a01b03161561210e5760405162461bcd60e51b815260206004820152601960248201527f5265776172647320746f6b656e20616c726561647920736574000000000000006044820152606401610b9c565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f45a4cbe003c343d60028e5acd63eecf588647b0eb369733afa2c0482180d4f74906020015b60405180910390a150565b600f546001600160a01b0316156121ac5760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff1661220e5760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b600d54604080516325ffda8160e21b815290516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169316916397ff6a04916004808301926020929190829003018186803b15801561227457600080fd5b505afa158015612288573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ac91906137c1565b6040517f19be8d120000000000000000000000000000000000000000000000000000000081526001600160d01b0319841660048201526001600160a01b0391909116906319be8d129060240160206040518083038186803b15801561231057600080fd5b505afa158015612324573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234891906137c1565b6001600160a01b03161461239e5760405162461bcd60e51b815260206004820152601160248201527f4d69736d617463686564206261736549640000000000000000000000000000006044820152606401610b9c565b600c805465ffffffffffff191660d083901c1790556040516001600160d01b0319821681527fa5a662d5f3165a00b47bd97ea0424c19490c0f263661390c2ab7dcedfa1a17ce90602001612158565b60005b8251811015610ef857612411610e8d84838151811061179757611797613f0f565b61244a5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b61246d83828151811061245f5761245f613f0f565b60200260200101518361338f565b8061247781613eb4565b9150506123f0565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff166124e15760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b600f546001600160a01b03161561252a5760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b6011546001600160a01b0316806125835760405162461bcd60e51b815260206004820152601160248201527f4e65787420706f6f6c206e6f74207365740000000000000000000000000000006044820152606401610b9c565b60008190506000816001600160a01b031663dc3bfba96040518163ffffffff1660e01b815260040160206040518083038186803b1580156125c357600080fd5b505afa1580156125d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125fb91906137c1565b60118054600f8054601080546001600160a01b038781166001600160a01b03199092169190911790915565ffffffffffff600160a01b808604918216026001600160d01b03199384168a8416171790935592169092556040516370a0823160e01b815230600482015292935060d09190911b916000917f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b1580156126b557600080fd5b505afa1580156126c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ed9190613bc7565b90506000811161273f5760405162461bcd60e51b815260206004820152601660248201527f4e6f2066756e647320746f2073746172742077697468000000000000000000006044820152606401610b9c565b6040516370a0823160e01b81526001600160a01b0385811660048301526000917f0000000000000000000000000000000000000000000000000000000000000000909116906370a082319060240160206040518083038186803b1580156127a557600080fd5b505afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127dd9190613bc7565b6040516370a0823160e01b81526001600160a01b0387811660048301529192506000918616906370a082319060240160206040518083038186803b15801561282457600080fd5b505afa158015612838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285c9190613bc7565b9050600061287d61286d8385613da8565b6128778587613dd4565b90613425565b9050600061288b8286613e1b565b600c549091506128d2906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691660100000000000090041683612f30565b6010546040517fb64b80840000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018490529091169063b64b808490604401600060405180830381600087803b15801561293957600080fd5b505af115801561294d573d6000803e3d6000fd5b506129879250506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690508984612f30565b6040517fb3f1c93d00000000000000000000000000000000000000000000000000000000815230600482018190526024820152604481018c9052606481018b90526001600160a01b0389169063b3f1c93d90608401606060405180830381600087803b1580156129f657600080fd5b505af1158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190613c02565b6012555050600154612a4857612a4633601254613309565b505b6040517f9e1f907b0000000000000000000000000000000000000000000000000000000081526001600160a01b038916600482015273dc3758330939a0253f30083a23e884377834899190639e1f907b9060240160206040518083038186803b158015612ab457600080fd5b505af4158015612ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aec9190613b9e565b6001600160a01b03891660008181526013602090815260409182902080546fffffffffffffffffffffffffffffffff19166001600160801b039590951694909417909355519081527fbf392a2214e536eb932a25b4490f99634f238baedb37418c3fd6de8923c94133910160405180910390a15050505050505050505050565b6001600160a01b03838116600081815260036020908152604080832094871680845294825280832086905551858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a35060019392505050565b60408051606081018252600a546001600160801b0381168252600160801b810463ffffffff908116602080850191909152600160a01b9092046bffffffffffffffffffffffff168385015283518085019094526009548082168086526401000000009091049091169184019190915260015491929190612c5442613345565b63ffffffff161015612c6557505050565b6000612c7d612c7342613345565b8460200151613468565b90506000846020015182612c919190613e32565b63ffffffff16905080612ca5575050505050565b8215612d1057612d048386604001516bffffffffffffffffffffffff1683670de0b6b3a7640000612cd69190613dd4565b612ce09190613dd4565b612cea9190613dc0565b8651612cff91906001600160801b0316613da8565b61348a565b6001600160801b031685525b63ffffffff8216602086018190528551600a80546040808a01516bffffffffffffffffffffffff16600160a01b026001600160a01b03600160801b9096026001600160a01b03199093166001600160801b03861617929092179490941617905590517fe972555b20cae8150e291bb40efce3ef4e3ed6b6b2c39c029346600e95469d4891612dac916001600160801b0391909116815260200190565b60405180910390a15050505050565b6001600160a01b0381166000908152600b602090815260408083208151808301835290546001600160801b038082168352600160801b9182900481168386019081528451606081018652600a5492831680825293830463ffffffff1696810196909652600160a01b9091046bffffffffffffffffffffffff16938501939093529151909291612ea391670de0b6b3a764000091612e589190613df3565b6001600160a01b038716600090815260026020526040902054612e84916001600160801b031690613dd4565b612e8e9190613dc0565b8351612cff91906001600160801b0316613da8565b6001600160801b0390811683528151811660208085019182526001600160a01b0387166000818152600b835260409081902087519451948616600160801b95909616948502861790558051918252918101939093528201527f5b9aaf4cc5141c090a75f8b8a627863eba92df81f0c83c096350da9b79aedd049060600160405180910390a1505192915050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691612fba9190613c8c565b6000604051808303816000865af19150503d8060008114612ff7576040519150601f19603f3d011682016040523d82523d6000602084013e612ffc565b606091505b509150915081801561302657508051158061302657508080602001905181019061302691906139c1565b61304c57613033816134d3565b60405162461bcd60e51b8152600401610b9c9190613d44565b5050505050565b60006001600160a01b03831633146130f3576001600160a01b038316600090815260036020908152604080832033845290915290205460001981146130f157828110156130e25760405162461bcd60e51b815260206004820152601c60248201527f45524332303a20496e73756666696369656e7420617070726f76616c000000006044820152606401610b9c565b6130ef8433858403612b6c565b505b505b50600192915050565b6000613106612bd5565b61310f84612dbb565b5061311983612dbb565b50610abd848484613532565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516131579190613ca8565b60408051918290038220828201825260018352603160f81b602093840152815180840194909452838201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606084015260808301949094523060a0808401919091528451808403909101815260c09092019093528051920191909120919050565b6001600160e01b031982166000908152602081815260408083206001600160a01b038516845290915290205460ff1615610f72576001600160e01b031982166000818152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339391927f4ddc7b757e7bdd7254a9cd39452d307a52761bc824625c6a33104a075d8099e691a45050565b6001600160e01b0319811661329e836001600160e01b03191660009081526020819052604090206001015460e01b90565b6001600160e01b03191614610f72576001600160e01b0319828116600081815260208190526040808220600101805463ffffffff191660e087901c17905551928416927fd348e2220a50b4500ec353f6e802d2f14dd1b5d6786148fd1bbcc570bf92d4739190a35050565b6000613313612bd5565b61331c83612dbb565b506109c58383613621565b6000613331612bd5565b61333a83612dbb565b506109c583836136ba565b600063ffffffff82111561338b5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b6044820152606401610b9c565b5090565b6001600160e01b031982166000908152602081815260408083206001600160a01b038516845290915290205460ff16610f72576001600160e01b031982166000818152602081815260408083206001600160a01b0386168085529252808320805460ff1916600117905551339391927fe6231789d19137da31d0550f4ba9ee379020a8cfb64cb79bf1790c996d2e616591a45050565b60006134318284613ecf565b15613453576134408284613dc0565b61344b906001613da8565b905080613461565b61345d8284613dc0565b9050805b5092915050565b60008163ffffffff168363ffffffff161061348357816109c5565b5090919050565b60006001600160801b0382111561338b5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b6044820152606401610b9c565b606060448251101561351857505060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c79000000602082015290565b60048201915081806020019051810190610f979190613a98565b6001600160a01b03831660009081526002602052604081205482111561359a5760405162461bcd60e51b815260206004820152601b60248201527f45524332303a20496e73756666696369656e742062616c616e636500000000006044820152606401610b9c565b6001600160a01b0380851660009081526002602052604080822080548690039055918516815220546135cd908390613da8565b6001600160a01b0380851660008181526002602052604090819020939093559151908616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612bc39086815260200190565b6001600160a01b038216600090815260026020526040812054613645908390613da8565b6001600160a01b03841660009081526002602052604090205560015461366c908390613da8565b6001556040518281526001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a350600192915050565b6001600160a01b0382166000908152600260205260408120548211156137225760405162461bcd60e51b815260206004820152601b60248201527f45524332303a20496e73756666696369656e742062616c616e636500000000006044820152606401610b9c565b6001600160a01b038316600081815260026020908152604080832080548790039055600180548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91016136a9565b803561378781613f3b565b919050565b80356001600160e01b03198116811461378757600080fd5b6000602082840312156137b657600080fd5b81356109c581613f3b565b6000602082840312156137d357600080fd5b81516109c581613f3b565b600080604083850312156137f157600080fd5b82356137fc81613f3b565b9150602083013561380c81613f3b565b809150509250929050565b60008060006060848603121561382c57600080fd5b833561383781613f3b565b9250602084013561384781613f3b565b929592945050506040919091013590565b600080600080600080600060e0888a03121561387357600080fd5b873561387e81613f3b565b9650602088013561388e81613f3b565b95506040880135945060608801359350608088013560ff811681146138b257600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156138e257600080fd5b82356138ed81613f3b565b946020939093013593505050565b6000806040838503121561390e57600080fd5b823567ffffffffffffffff8082111561392657600080fd5b818501915085601f83011261393a57600080fd5b813560208282111561394e5761394e613f25565b8160051b925061395f818401613d77565b8281528181019085830185870184018b101561397a57600080fd5b600096505b848710156139a4576139908161378c565b83526001969096019591830191830161397f565b5096506139b4905087820161377c565b9450505050509250929050565b6000602082840312156139d357600080fd5b815180151581146109c557600080fd5b6000602082840312156139f557600080fd5b6109c58261378c565b60008060408385031215613a1157600080fd5b6137fc8361378c565b60008060408385031215613a2d57600080fd5b613a368361378c565b9150613a446020840161378c565b90509250929050565b600060208284031215613a5f57600080fd5b81356109c581613f53565b60008060408385031215613a7d57600080fd5b8235613a8881613f3b565b9150602083013561380c81613f53565b600060208284031215613aaa57600080fd5b815167ffffffffffffffff80821115613ac257600080fd5b818401915084601f830112613ad657600080fd5b815181811115613ae857613ae8613f25565b613afb601f8201601f1916602001613d77565b9150808252856020828501011115613b1257600080fd5b613b23816020840160208601613e4f565b50949350505050565b600060608284031215613b3e57600080fd5b6040516060810181811067ffffffffffffffff82111715613b6157613b61613f25565b6040528251613b6f81613f3b565b81526020830151613b7f81613f53565b60208201526040830151613b9281613f69565b60408201529392505050565b600060208284031215613bb057600080fd5b81516001600160801b03811681146109c557600080fd5b600060208284031215613bd957600080fd5b5051919050565b60008060408385031215613bf357600080fd5b50508035926020909101359150565b600080600060608486031215613c1757600080fd5b8351925060208401519150604084015190509250925092565b600080600060608486031215613c4557600080fd5b8335613c5081613f69565b92506020840135613c6081613f69565b915060408401356bffffffffffffffffffffffff81168114613c8157600080fd5b809150509250925092565b60008251613c9e818460208701613e4f565b9190910192915050565b600080835481600182811c915080831680613cc457607f831692505b6020808410821415613ce457634e487b7160e01b86526022600452602486fd5b818015613cf85760018114613d0957613d36565b60ff19861689528489019650613d36565b60008a81526020902060005b86811015613d2e5781548b820152908501908301613d15565b505084890196505b509498975050505050505050565b6020815260008251806020840152613d63816040850160208701613e4f565b601f01601f19169190910160400192915050565b604051601f8201601f1916810167ffffffffffffffff81118282101715613da057613da0613f25565b604052919050565b60008219821115613dbb57613dbb613ee3565b500190565b600082613dcf57613dcf613ef9565b500490565b6000816000190483118215151615613dee57613dee613ee3565b500290565b60006001600160801b0383811690831681811015613e1357613e13613ee3565b039392505050565b600082821015613e2d57613e2d613ee3565b500390565b600063ffffffff83811690831681811015613e1357613e13613ee3565b60005b83811015613e6a578181015183820152602001613e52565b83811115613e79576000848401525b50505050565b600181811c90821680613e9357607f821691505b602082108114156119ed57634e487b7160e01b600052602260045260246000fd5b6000600019821415613ec857613ec8613ee3565b5060010190565b600082613ede57613ede613ef9565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613f5057600080fd5b50565b6001600160d01b031981168114613f5057600080fd5b63ffffffff81168114613f5057600080fdfea264697066735822122049af07b32bb63c724ae6146d9c9ce70501d8420cc4ca495dd760cd5e6f8540bc64736f6c6343000806003300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000006cb18ff2a33e981d1e38a663ca056c0a5265066a000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc23030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d5969656c642053747261746567792045544820364d204d61722053657000000000000000000000000000000000000000000000000000000000000000000000095953455448364d4d530000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103735760003560e01c80637ecebe00116101d3578063cd0d009611610104578063de02cde7116100a2578063e9e5d6d01161007c578063e9e5d6d0146108f1578063effae35314610904578063f8c2b77314610917578063ffffffff1461077b57600080fd5b8063de02cde71461088a578063de320cc11461089d578063dea587b0146108b057600080fd5b8063d95edafe116100de578063d95edafe14610823578063dc3bfba914610836578063dd46e85414610849578063dd62ed3e1461085157600080fd5b8063cd0d0096146107d6578063d1af0c7d146107fd578063d505accf1461081057600080fd5b806397ff6a0411610171578063a9059cbb1161014b578063a9059cbb1461078a578063ad82110f1461079d578063ae93c1b5146107b0578063ba3573b0146107c357600080fd5b806397ff6a0414610755578063a354f39e14610768578063a4f0d7d01461077b57600080fd5b80638cc96ac5116101ad5780638cc96ac51461071d5780639326295b1461073157806394b8e38f1461073a57806395d89b411461074d57600080fd5b80637ecebe00146106d75780638737a2dc146106f757806389afcb441461070a57600080fd5b806330adf81f116102ad5780635909c12f1161024b5780636a627842116102255780636a627842146106175780636ed3e3e31461062a57806370641a361461063e57806370a08231146106ae57600080fd5b80635909c12f146103785780635ba5e9f0146105f1578063687f0e4c1461060457600080fd5b806344faded01161028757806344faded0146105875780635001f3b51461059a57806354fd4d50146105c1578063559742d9146105de57600080fd5b806330adf81f14610539578063313ce567146105605780633644e5151461057f57600080fd5b806318160ddd1161031a578063243d6585116102f4578063243d6585146104bd57806326ae2b78146104d057806328c3b85c146105095780632d42cf7d1461052f57600080fd5b806318160ddd146104855780631e83409a1461049757806323b872dd146104aa57600080fd5b80630700037d116103565780630700037d146103e8578063095ea7b31461043c57806310ab94321461045f57806316f0115b1461047257600080fd5b8015610378578063068b8a801461039e57806306fdde03146103d3575b600080fd5b610380600081565b6040516001600160e01b031990911681526020015b60405180910390f35b600c546103bb90660100000000000090046001600160a01b031681565b6040516001600160a01b039091168152602001610395565b6103db61092a565b6040516103959190613d44565b61041c6103f63660046137a4565b600b602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b03938416815292909116602083015201610395565b61044f61044a3660046138cf565b6109b8565b6040519015158152602001610395565b61044f61046d3660046139fe565b6109cc565b600f546103bb906001600160a01b031681565b6001545b604051908152602001610395565b6104896104a53660046137a4565b610a00565b61044f6104b8366004613817565b610aa5565b6011546103bb906001600160a01b031681565b6009546104ec9063ffffffff8082169164010000000090041682565b6040805163ffffffff938416815292909116602083015201610395565b600c546105169060d01b81565b6040516001600160d01b03199091168152602001610395565b610537610ac5565b005b6104897f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065461056d9060ff1681565b60405160ff9091168152602001610395565b610489610e07565b6105376105953660046139fe565b610e63565b6103bb7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6040805180820190915260018152603160f81b60208201526103db565b6105376105ec3660046139e3565b610efd565b6103806105ff3660046139e3565b610f76565b6105376106123660046139fe565b610f9d565b6104896106253660046137a4565b610fff565b60115461051690600160a01b900460d01b81565b600a54610676906001600160801b03811690600160801b810463ffffffff1690600160a01b90046bffffffffffffffffffffffff1683565b604080516001600160801b03909416845263ffffffff90921660208401526bffffffffffffffffffffffff1690820152606001610395565b6104896106bc3660046137a4565b6001600160a01b031660009081526002602052604090205490565b6104896106e53660046137a4565b60076020526000908152604090205481565b610537610705366004613a6a565b611123565b6104896107183660046137a4565b61144a565b600f5461051690600160a01b900460d01b81565b61048960125481565b600d546103bb906001600160a01b031681565b6103db611507565b600e546103bb906001600160a01b031681565b610537610776366004613c30565b611514565b6103806001600160e01b031981565b61044f6107983660046138cf565b611766565b6105376107ab3660046138fb565b611773565b6105376107be366004613a1a565b61182f565b6104896107d13660046137a4565b61189c565b6104897f000000000000000000000000000000000000000000000000000000000000000181565b6008546103bb906001600160a01b031681565b61053761081e366004613858565b6119f3565b6105376108313660046137a4565b611c7d565b6010546103bb906001600160a01b031681565b610537611e19565b61048961085f3660046137de565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b6105376108983660046139fe565b611fe6565b6105376108ab3660046137a4565b612053565b6108d96108be3660046137a4565b6013602052600090815260409020546001600160801b031681565b6040516001600160801b039091168152602001610395565b6105376108ff366004613a4d565b612163565b6105376109123660046138fb565b6123ed565b610537610925366004613be0565b61247f565b6004805461093790613e7f565b80601f016020809104026020016040519081016040528092919081815260200182805461096390613e7f565b80156109b05780601f10610985576101008083540402835291602001916109b0565b820191906000526020600020905b81548152906001019060200180831161099357829003601f168201915b505050505081565b60006109c5338484612b6c565b9392505050565b6001600160e01b031982166000908152602081815260408083206001600160a01b038516845290915281205460ff166109c5565b6000610a0a612bd5565b610a1333612dbb565b336000908152600b6020526040902080546fffffffffffffffffffffffffffffffff191690556008546001600160801b03919091169150610a5e906001600160a01b03168383612f30565b604080516001600160a01b0384168152602081018390527fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a910160405180910390a1919050565b6000610ab18483613053565b50610abd8484846130fc565b949350505050565b601060009054906101000a90046001600160a01b03166001600160a01b031663204f83f96040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1357600080fd5b505afa158015610b27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4b9190613bc7565b4263ffffffff161015610ba55760405162461bcd60e51b815260206004820152601360248201527f4f6e6c79206166746572206d617475726974790000000000000000000000000060448201526064015b60405180910390fd5b600f546010546040516370a0823160e01b81523060048201526001600160a01b03928316929091169060009083906370a082319060240160206040518083038186803b158015610bf457600080fd5b505afa158015610c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2c9190613bc7565b9050610c426001600160a01b0384168483612f30565b6040517fd7020d0a000000000000000000000000000000000000000000000000000000008152306004820181905260248201526000604482018190526000196064830152906001600160a01b0385169063d7020d0a90608401606060405180830381600087803b158015610cb557600080fd5b505af1158015610cc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ced9190613c02565b9250610d069150506001600160a01b0384168483612f30565b6040517f1e9a6950000000000000000000000000000000000000000000000000000000008152306004820152602481018290526001600160a01b03841690631e9a695090604401602060405180830381600087803b158015610d6757600080fd5b505af1158015610d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9f9190613bc7565b506040516001600160a01b03851681527ffeba534d95469be2b9f083643be5f83b8ffd5aba9b64b79f3e71e51acd5c87a29060200160405180910390a15050600f8054601080546001600160a01b03191690556001600160d01b031916905550506000601255565b60007f00000000000000000000000000000000000000000000000000000000000000014614610e3e57610e3946613125565b905090565b507fb0557cf77256f5cbabc9519b10d80c8c34a5afa6451956e0e4e1cfcbeb9ed73390565b81610eb5610e8d826001600160e01b03191660009081526020819052604090206001015460e01b90565b6001600160e01b03191660009081526020818152604080832033845290915290205460ff1690565b610eee5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b610ef883836131d9565b505050565b80610f27610e8d826001600160e01b03191660009081526020819052604090206001015460e01b90565b610f605760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b610f72826001600160e01b031961326d565b5050565b6001600160e01b0319811660009081526020819052604081206001015460e01b5b92915050565b6001600160a01b0381163314610ff55760405162461bcd60e51b815260206004820152601660248201527f52656e6f756e6365206f6e6c7920666f722073656c66000000000000000000006044820152606401610b9c565b610f7282826131d9565b600f546000906001600160a01b031661105a5760405162461bcd60e51b815260206004820152601160248201527f506f6f6c206e6f742073656c65637465640000000000000000000000000000006044820152606401610b9c565b601254600f546040516370a0823160e01b815230600482015260009183916001600160a01b03909116906370a082319060240160206040518083038186803b1580156110a557600080fd5b505afa1580156110b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190613bc7565b6110e79190613e1b565b905081816001546110f89190613dd4565b6111029190613dc0565b925061110e8183613da8565b60125561111b8484613309565b505050919050565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff166111855760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b816001600160a01b0316635001f3b56040518163ffffffff1660e01b815260040160206040518083038186803b1580156111be57600080fd5b505afa1580156111d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f691906137c1565b6001600160a01b03167f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316146112765760405162461bcd60e51b815260206004820152600f60248201527f4d69736d617463686564206261736500000000000000000000000000000000006044820152606401610b9c565b600e546040517f55d03e340000000000000000000000000000000000000000000000000000000081526001600160d01b0319831660048201526000916001600160a01b0316906355d03e349060240160606040518083038186803b1580156112dd57600080fd5b505afa1580156112f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113159190613b2c565b9050826001600160a01b031663dc3bfba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561135057600080fd5b505afa158015611364573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138891906137c1565b6001600160a01b031681600001516001600160a01b0316146113ec5760405162461bcd60e51b815260206004820152601360248201527f4d69736d617463686564207365726965734964000000000000000000000000006044820152606401610b9c565b601180546001600160a01b0385166001600160d01b03199182168117600160a01b60d087901c021790925560405190841691907fa0868ad381d06fdaa9677c62624fe2c7bdcfb52ff9147345f2b1b691f3f5ec7d90600090a3505050565b600f546000906001600160a01b03166114a55760405162461bcd60e51b815260206004820152601160248201527f506f6f6c206e6f742073656c65637465640000000000000000000000000000006044820152606401610b9c565b601254306000908152600260205260409020546001546114c58284613dd4565b6114cf9190613dc0565b92506114db8383613e1b565b6012556114e83082613327565b50600f54611500906001600160a01b03168585612f30565b5050919050565b6005805461093790613e7f565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff166115765760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b8163ffffffff168363ffffffff1611156115d25760405162461bcd60e51b815260206004820152600f60248201527f496e636f727265637420696e70757400000000000000000000000000000000006044820152606401610b9c565b6008546001600160a01b031661162a5760405162461bcd60e51b815260206004820152601560248201527f5265776172647320746f6b656e206e6f742073657400000000000000000000006044820152606401610b9c565b60095463ffffffff1661163c42613345565b63ffffffff16108061166b5750600954640100000000900463ffffffff1661166342613345565b63ffffffff16115b6116b75760405162461bcd60e51b815260206004820152600f60248201527f4f6e676f696e67207265776172647300000000000000000000000000000000006044820152606401610b9c565b6009805463ffffffff85811667ffffffffffffffff19909216821764010000000091861691820217909255600a80546001600160801b0316600160801b83026001600160a01b031617600160a01b6bffffffffffffffffffffffff861690810291909117909155604080519283526020830193909352918101919091527f95efd8a2a0aa591f48fd9673cf5d13c2150ca7a1fe1cbe438dd3f0ae470646639060600160405180910390a1505050565b60006109c53384846130fc565b60005b8251811015610ef8576117c1610e8d84838151811061179757611797613f0f565b60200260200101516001600160e01b03191660009081526020819052604090206001015460e01b90565b6117fa5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b61181d83828151811061180f5761180f613f0f565b6020026020010151836131d9565b8061182781613eb4565b915050611776565b81611859610e8d826001600160e01b03191660009081526020819052604090206001015460e01b90565b6118925760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b610ef8838361326d565b600f546000906001600160a01b0316156118e85760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b30600081815260026020526040908190205460015491516370a0823160e01b815260048101939093529182906001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216906370a082319060240160206040518083038186803b15801561196057600080fd5b505afa158015611974573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119989190613bc7565b6119a29190613dd4565b6119ac9190613dc0565b91506119b83082613327565b506119ed6001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2168484612f30565b50919050565b42841015611a435760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610b9c565b6001600160a01b038716600090815260076020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a919086611a9083613eb4565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060007f00000000000000000000000000000000000000000000000000000000000000014614611b1b57611b1646613125565b611b3d565b7fb0557cf77256f5cbabc9519b10d80c8c34a5afa6451956e0e4e1cfcbeb9ed7335b6040517f1901000000000000000000000000000000000000000000000000000000000000602082015260228101919091526042810183905260620160408051601f198184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015611be3573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611c195750896001600160a01b0316816001600160a01b0316145b611c655760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610b9c565b611c708a8a8a612b6c565b5050505050505050505050565b600f546001600160a01b031615611cc65760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff16611d285760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b600d80546001600160a01b0319166001600160a01b038316908117909155604080516325ffda8160e21b81529051600092916397ff6a04916004808301926020929190829003018186803b158015611d7f57600080fd5b505afa158015611d93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db791906137c1565b600e80546001600160a01b0319166001600160a01b0383811691821790925560408051928616835260208301919091529192507f2fe4e5ef899cc1bf6c10bd764667743de04f9dfe0ad51bbc956f4539b4f8a654910160405180910390a15050565b600f546001600160a01b031615611e625760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff16611ec45760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b600d54600c546040517f60e0b63600000000000000000000000000000000000000000000000000000000815260d09190911b6001600160d01b03191660048201526001600160a01b03909116906360e0b6369060240160206040518083038186803b158015611f3257600080fd5b505afa158015611f46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6a91906137c1565b600c80547fffffffffffff0000000000000000000000000000000000000000ffffffffffff1666010000000000006001600160a01b0393841681029190911791829055604051910490911681527f9261f5bf303fa2594f2b969e042420fc0125c062081305ab742561823f41c8f89060200160405180910390a1565b81612010610e8d826001600160e01b03191660009081526020819052604090206001015460e01b90565b6120495760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b610ef8838361338f565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff166120b55760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b6008546001600160a01b03161561210e5760405162461bcd60e51b815260206004820152601960248201527f5265776172647320746f6b656e20616c726561647920736574000000000000006044820152606401610b9c565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f45a4cbe003c343d60028e5acd63eecf588647b0eb369733afa2c0482180d4f74906020015b60405180910390a150565b600f546001600160a01b0316156121ac5760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff1661220e5760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b600d54604080516325ffda8160e21b815290516001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281169316916397ff6a04916004808301926020929190829003018186803b15801561227457600080fd5b505afa158015612288573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ac91906137c1565b6040517f19be8d120000000000000000000000000000000000000000000000000000000081526001600160d01b0319841660048201526001600160a01b0391909116906319be8d129060240160206040518083038186803b15801561231057600080fd5b505afa158015612324573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234891906137c1565b6001600160a01b03161461239e5760405162461bcd60e51b815260206004820152601160248201527f4d69736d617463686564206261736549640000000000000000000000000000006044820152606401610b9c565b600c805465ffffffffffff191660d083901c1790556040516001600160d01b0319821681527fa5a662d5f3165a00b47bd97ea0424c19490c0f263661390c2ab7dcedfa1a17ce90602001612158565b60005b8251811015610ef857612411610e8d84838151811061179757611797613f0f565b61244a5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b6044820152606401610b9c565b61246d83828151811061245f5761245f613f0f565b60200260200101518361338f565b8061247781613eb4565b9150506123f0565b600080356001600160e01b03191681526020818152604080832033845290915290205460ff166124e15760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606401610b9c565b600f546001600160a01b03161561252a5760405162461bcd60e51b815260206004820152600d60248201526c141bdbdb081cd95b1958dd1959609a1b6044820152606401610b9c565b6011546001600160a01b0316806125835760405162461bcd60e51b815260206004820152601160248201527f4e65787420706f6f6c206e6f74207365740000000000000000000000000000006044820152606401610b9c565b60008190506000816001600160a01b031663dc3bfba96040518163ffffffff1660e01b815260040160206040518083038186803b1580156125c357600080fd5b505afa1580156125d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125fb91906137c1565b60118054600f8054601080546001600160a01b038781166001600160a01b03199092169190911790915565ffffffffffff600160a01b808604918216026001600160d01b03199384168a8416171790935592169092556040516370a0823160e01b815230600482015292935060d09190911b916000917f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216906370a082319060240160206040518083038186803b1580156126b557600080fd5b505afa1580156126c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ed9190613bc7565b90506000811161273f5760405162461bcd60e51b815260206004820152601660248201527f4e6f2066756e647320746f2073746172742077697468000000000000000000006044820152606401610b9c565b6040516370a0823160e01b81526001600160a01b0385811660048301526000917f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2909116906370a082319060240160206040518083038186803b1580156127a557600080fd5b505afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127dd9190613bc7565b6040516370a0823160e01b81526001600160a01b0387811660048301529192506000918616906370a082319060240160206040518083038186803b15801561282457600080fd5b505afa158015612838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285c9190613bc7565b9050600061287d61286d8385613da8565b6128778587613dd4565b90613425565b9050600061288b8286613e1b565b600c549091506128d2906001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2811691660100000000000090041683612f30565b6010546040517fb64b80840000000000000000000000000000000000000000000000000000000081526001600160a01b038a81166004830152602482018490529091169063b64b808490604401600060405180830381600087803b15801561293957600080fd5b505af115801561294d573d6000803e3d6000fd5b506129879250506001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21690508984612f30565b6040517fb3f1c93d00000000000000000000000000000000000000000000000000000000815230600482018190526024820152604481018c9052606481018b90526001600160a01b0389169063b3f1c93d90608401606060405180830381600087803b1580156129f657600080fd5b505af1158015612a0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2e9190613c02565b6012555050600154612a4857612a4633601254613309565b505b6040517f9e1f907b0000000000000000000000000000000000000000000000000000000081526001600160a01b038916600482015273dc3758330939a0253f30083a23e884377834899190639e1f907b9060240160206040518083038186803b158015612ab457600080fd5b505af4158015612ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aec9190613b9e565b6001600160a01b03891660008181526013602090815260409182902080546fffffffffffffffffffffffffffffffff19166001600160801b039590951694909417909355519081527fbf392a2214e536eb932a25b4490f99634f238baedb37418c3fd6de8923c94133910160405180910390a15050505050505050505050565b6001600160a01b03838116600081815260036020908152604080832094871680845294825280832086905551858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a35060019392505050565b60408051606081018252600a546001600160801b0381168252600160801b810463ffffffff908116602080850191909152600160a01b9092046bffffffffffffffffffffffff168385015283518085019094526009548082168086526401000000009091049091169184019190915260015491929190612c5442613345565b63ffffffff161015612c6557505050565b6000612c7d612c7342613345565b8460200151613468565b90506000846020015182612c919190613e32565b63ffffffff16905080612ca5575050505050565b8215612d1057612d048386604001516bffffffffffffffffffffffff1683670de0b6b3a7640000612cd69190613dd4565b612ce09190613dd4565b612cea9190613dc0565b8651612cff91906001600160801b0316613da8565b61348a565b6001600160801b031685525b63ffffffff8216602086018190528551600a80546040808a01516bffffffffffffffffffffffff16600160a01b026001600160a01b03600160801b9096026001600160a01b03199093166001600160801b03861617929092179490941617905590517fe972555b20cae8150e291bb40efce3ef4e3ed6b6b2c39c029346600e95469d4891612dac916001600160801b0391909116815260200190565b60405180910390a15050505050565b6001600160a01b0381166000908152600b602090815260408083208151808301835290546001600160801b038082168352600160801b9182900481168386019081528451606081018652600a5492831680825293830463ffffffff1696810196909652600160a01b9091046bffffffffffffffffffffffff16938501939093529151909291612ea391670de0b6b3a764000091612e589190613df3565b6001600160a01b038716600090815260026020526040902054612e84916001600160801b031690613dd4565b612e8e9190613dc0565b8351612cff91906001600160801b0316613da8565b6001600160801b0390811683528151811660208085019182526001600160a01b0387166000818152600b835260409081902087519451948616600160801b95909616948502861790558051918252918101939093528201527f5b9aaf4cc5141c090a75f8b8a627863eba92df81f0c83c096350da9b79aedd049060600160405180910390a1505192915050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691612fba9190613c8c565b6000604051808303816000865af19150503d8060008114612ff7576040519150601f19603f3d011682016040523d82523d6000602084013e612ffc565b606091505b509150915081801561302657508051158061302657508080602001905181019061302691906139c1565b61304c57613033816134d3565b60405162461bcd60e51b8152600401610b9c9190613d44565b5050505050565b60006001600160a01b03831633146130f3576001600160a01b038316600090815260036020908152604080832033845290915290205460001981146130f157828110156130e25760405162461bcd60e51b815260206004820152601c60248201527f45524332303a20496e73756666696369656e7420617070726f76616c000000006044820152606401610b9c565b6130ef8433858403612b6c565b505b505b50600192915050565b6000613106612bd5565b61310f84612dbb565b5061311983612dbb565b50610abd848484613532565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516131579190613ca8565b60408051918290038220828201825260018352603160f81b602093840152815180840194909452838201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606084015260808301949094523060a0808401919091528451808403909101815260c09092019093528051920191909120919050565b6001600160e01b031982166000908152602081815260408083206001600160a01b038516845290915290205460ff1615610f72576001600160e01b031982166000818152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339391927f4ddc7b757e7bdd7254a9cd39452d307a52761bc824625c6a33104a075d8099e691a45050565b6001600160e01b0319811661329e836001600160e01b03191660009081526020819052604090206001015460e01b90565b6001600160e01b03191614610f72576001600160e01b0319828116600081815260208190526040808220600101805463ffffffff191660e087901c17905551928416927fd348e2220a50b4500ec353f6e802d2f14dd1b5d6786148fd1bbcc570bf92d4739190a35050565b6000613313612bd5565b61331c83612dbb565b506109c58383613621565b6000613331612bd5565b61333a83612dbb565b506109c583836136ba565b600063ffffffff82111561338b5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b6044820152606401610b9c565b5090565b6001600160e01b031982166000908152602081815260408083206001600160a01b038516845290915290205460ff16610f72576001600160e01b031982166000818152602081815260408083206001600160a01b0386168085529252808320805460ff1916600117905551339391927fe6231789d19137da31d0550f4ba9ee379020a8cfb64cb79bf1790c996d2e616591a45050565b60006134318284613ecf565b15613453576134408284613dc0565b61344b906001613da8565b905080613461565b61345d8284613dc0565b9050805b5092915050565b60008163ffffffff168363ffffffff161061348357816109c5565b5090919050565b60006001600160801b0382111561338b5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b6044820152606401610b9c565b606060448251101561351857505060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c79000000602082015290565b60048201915081806020019051810190610f979190613a98565b6001600160a01b03831660009081526002602052604081205482111561359a5760405162461bcd60e51b815260206004820152601b60248201527f45524332303a20496e73756666696369656e742062616c616e636500000000006044820152606401610b9c565b6001600160a01b0380851660009081526002602052604080822080548690039055918516815220546135cd908390613da8565b6001600160a01b0380851660008181526002602052604090819020939093559151908616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612bc39086815260200190565b6001600160a01b038216600090815260026020526040812054613645908390613da8565b6001600160a01b03841660009081526002602052604090205560015461366c908390613da8565b6001556040518281526001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a350600192915050565b6001600160a01b0382166000908152600260205260408120548211156137225760405162461bcd60e51b815260206004820152601b60248201527f45524332303a20496e73756666696369656e742062616c616e636500000000006044820152606401610b9c565b6001600160a01b038316600081815260026020908152604080832080548790039055600180548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91016136a9565b803561378781613f3b565b919050565b80356001600160e01b03198116811461378757600080fd5b6000602082840312156137b657600080fd5b81356109c581613f3b565b6000602082840312156137d357600080fd5b81516109c581613f3b565b600080604083850312156137f157600080fd5b82356137fc81613f3b565b9150602083013561380c81613f3b565b809150509250929050565b60008060006060848603121561382c57600080fd5b833561383781613f3b565b9250602084013561384781613f3b565b929592945050506040919091013590565b600080600080600080600060e0888a03121561387357600080fd5b873561387e81613f3b565b9650602088013561388e81613f3b565b95506040880135945060608801359350608088013560ff811681146138b257600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156138e257600080fd5b82356138ed81613f3b565b946020939093013593505050565b6000806040838503121561390e57600080fd5b823567ffffffffffffffff8082111561392657600080fd5b818501915085601f83011261393a57600080fd5b813560208282111561394e5761394e613f25565b8160051b925061395f818401613d77565b8281528181019085830185870184018b101561397a57600080fd5b600096505b848710156139a4576139908161378c565b83526001969096019591830191830161397f565b5096506139b4905087820161377c565b9450505050509250929050565b6000602082840312156139d357600080fd5b815180151581146109c557600080fd5b6000602082840312156139f557600080fd5b6109c58261378c565b60008060408385031215613a1157600080fd5b6137fc8361378c565b60008060408385031215613a2d57600080fd5b613a368361378c565b9150613a446020840161378c565b90509250929050565b600060208284031215613a5f57600080fd5b81356109c581613f53565b60008060408385031215613a7d57600080fd5b8235613a8881613f3b565b9150602083013561380c81613f53565b600060208284031215613aaa57600080fd5b815167ffffffffffffffff80821115613ac257600080fd5b818401915084601f830112613ad657600080fd5b815181811115613ae857613ae8613f25565b613afb601f8201601f1916602001613d77565b9150808252856020828501011115613b1257600080fd5b613b23816020840160208601613e4f565b50949350505050565b600060608284031215613b3e57600080fd5b6040516060810181811067ffffffffffffffff82111715613b6157613b61613f25565b6040528251613b6f81613f3b565b81526020830151613b7f81613f53565b60208201526040830151613b9281613f69565b60408201529392505050565b600060208284031215613bb057600080fd5b81516001600160801b03811681146109c557600080fd5b600060208284031215613bd957600080fd5b5051919050565b60008060408385031215613bf357600080fd5b50508035926020909101359150565b600080600060608486031215613c1757600080fd5b8351925060208401519150604084015190509250925092565b600080600060608486031215613c4557600080fd5b8335613c5081613f69565b92506020840135613c6081613f69565b915060408401356bffffffffffffffffffffffff81168114613c8157600080fd5b809150509250925092565b60008251613c9e818460208701613e4f565b9190910192915050565b600080835481600182811c915080831680613cc457607f831692505b6020808410821415613ce457634e487b7160e01b86526022600452602486fd5b818015613cf85760018114613d0957613d36565b60ff19861689528489019650613d36565b60008a81526020902060005b86811015613d2e5781548b820152908501908301613d15565b505084890196505b509498975050505050505050565b6020815260008251806020840152613d63816040850160208701613e4f565b601f01601f19169190910160400192915050565b604051601f8201601f1916810167ffffffffffffffff81118282101715613da057613da0613f25565b604052919050565b60008219821115613dbb57613dbb613ee3565b500190565b600082613dcf57613dcf613ef9565b500490565b6000816000190483118215151615613dee57613dee613ee3565b500290565b60006001600160801b0383811690831681811015613e1357613e13613ee3565b039392505050565b600082821015613e2d57613e2d613ee3565b500390565b600063ffffffff83811690831681811015613e1357613e13613ee3565b60005b83811015613e6a578181015183820152602001613e52565b83811115613e79576000848401525b50505050565b600181811c90821680613e9357607f821691505b602082108114156119ed57634e487b7160e01b600052602260045260246000fd5b6000600019821415613ec857613ec8613ee3565b5060010190565b600082613ede57613ede613ef9565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613f5057600080fd5b50565b6001600160d01b031981168114613f5057600080fd5b63ffffffff81168114613f5057600080fdfea264697066735822122049af07b32bb63c724ae6146d9c9ce70501d8420cc4ca495dd760cd5e6f8540bc64736f6c63430008060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000006cb18ff2a33e981d1e38a663ca056c0a5265066a000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc23030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d5969656c642053747261746567792045544820364d204d61722053657000000000000000000000000000000000000000000000000000000000000000000000095953455448364d4d530000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name (string): Yield Strategy ETH 6M Mar Sep
Arg [1] : symbol (string): YSETH6MMS
Arg [2] : ladle_ (address): 0x6cB18fF2A33e981D1e38A663Ca056c0a5265066A
Arg [3] : base_ (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [4] : baseId_ (bytes6): 0x303000000000
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000006cb18ff2a33e981d1e38a663ca056c0a5265066a
Arg [3] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [4] : 3030000000000000000000000000000000000000000000000000000000000000
Arg [5] : 000000000000000000000000000000000000000000000000000000000000001d
Arg [6] : 5969656c642053747261746567792045544820364d204d617220536570000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [8] : 5953455448364d4d530000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.