More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Nominate New Own... | 14880299 | 986 days ago | IN | 0 ETH | 0.00214927 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TWAMM_AMO
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-05-31 */ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // Sources flattened with hardhat v2.9.6 https://hardhat.org // File contracts/Frax/IFrax.sol interface IFrax { function COLLATERAL_RATIO_PAUSER() external view returns (bytes32); function DEFAULT_ADMIN_ADDRESS() external view returns (address); function DEFAULT_ADMIN_ROLE() external view returns (bytes32); function addPool(address pool_address ) external; function allowance(address owner, address spender ) external view returns (uint256); function approve(address spender, uint256 amount ) external returns (bool); function balanceOf(address account ) external view returns (uint256); function burn(uint256 amount ) external; function burnFrom(address account, uint256 amount ) external; function collateral_ratio_paused() external view returns (bool); function controller_address() external view returns (address); function creator_address() external view returns (address); function decimals() external view returns (uint8); function decreaseAllowance(address spender, uint256 subtractedValue ) external returns (bool); function eth_usd_consumer_address() external view returns (address); function eth_usd_price() external view returns (uint256); function frax_eth_oracle_address() external view returns (address); function frax_info() external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256); function frax_pools(address ) external view returns (bool); function frax_pools_array(uint256 ) external view returns (address); function frax_price() external view returns (uint256); function frax_step() external view returns (uint256); function fxs_address() external view returns (address); function fxs_eth_oracle_address() external view returns (address); function fxs_price() external view returns (uint256); function genesis_supply() external view returns (uint256); function getRoleAdmin(bytes32 role ) external view returns (bytes32); function getRoleMember(bytes32 role, uint256 index ) external view returns (address); function getRoleMemberCount(bytes32 role ) external view returns (uint256); function globalCollateralValue() external view returns (uint256); function global_collateral_ratio() external view returns (uint256); function grantRole(bytes32 role, address account ) external; function hasRole(bytes32 role, address account ) external view returns (bool); function increaseAllowance(address spender, uint256 addedValue ) external returns (bool); function last_call_time() external view returns (uint256); function minting_fee() external view returns (uint256); function name() external view returns (string memory); function owner_address() external view returns (address); function pool_burn_from(address b_address, uint256 b_amount ) external; function pool_mint(address m_address, uint256 m_amount ) external; function price_band() external view returns (uint256); function price_target() external view returns (uint256); function redemption_fee() external view returns (uint256); function refreshCollateralRatio() external; function refresh_cooldown() external view returns (uint256); function removePool(address pool_address ) external; function renounceRole(bytes32 role, address account ) external; function revokeRole(bytes32 role, address account ) external; function setController(address _controller_address ) external; function setETHUSDOracle(address _eth_usd_consumer_address ) external; function setFRAXEthOracle(address _frax_oracle_addr, address _weth_address ) external; function setFXSAddress(address _fxs_address ) external; function setFXSEthOracle(address _fxs_oracle_addr, address _weth_address ) external; function setFraxStep(uint256 _new_step ) external; function setMintingFee(uint256 min_fee ) external; function setOwner(address _owner_address ) external; function setPriceBand(uint256 _price_band ) external; function setPriceTarget(uint256 _new_price_target ) external; function setRedemptionFee(uint256 red_fee ) external; function setRefreshCooldown(uint256 _new_cooldown ) external; function setTimelock(address new_timelock ) external; function symbol() external view returns (string memory); function timelock_address() external view returns (address); function toggleCollateralRatio() external; function totalSupply() external view returns (uint256); function transfer(address recipient, uint256 amount ) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool); function weth_address() external view returns (address); } // File contracts/FXS/IFxs.sol interface IFxs { function DEFAULT_ADMIN_ROLE() external view returns(bytes32); function FRAXStablecoinAdd() external view returns(address); function FXS_DAO_min() external view returns(uint256); function allowance(address owner, address spender) external view returns(uint256); function approve(address spender, uint256 amount) external returns(bool); function balanceOf(address account) external view returns(uint256); function burn(uint256 amount) external; function burnFrom(address account, uint256 amount) external; function checkpoints(address, uint32) external view returns(uint32 fromBlock, uint96 votes); function decimals() external view returns(uint8); function decreaseAllowance(address spender, uint256 subtractedValue) external returns(bool); function genesis_supply() external view returns(uint256); function getCurrentVotes(address account) external view returns(uint96); function getPriorVotes(address account, uint256 blockNumber) external view returns(uint96); function getRoleAdmin(bytes32 role) external view returns(bytes32); function getRoleMember(bytes32 role, uint256 index) external view returns(address); function getRoleMemberCount(bytes32 role) external view returns(uint256); function grantRole(bytes32 role, address account) external; function hasRole(bytes32 role, address account) external view returns(bool); function increaseAllowance(address spender, uint256 addedValue) external returns(bool); function mint(address to, uint256 amount) external; function name() external view returns(string memory); function numCheckpoints(address) external view returns(uint32); function oracle_address() external view returns(address); function owner_address() external view returns(address); function pool_burn_from(address b_address, uint256 b_amount) external; function pool_mint(address m_address, uint256 m_amount) external; function renounceRole(bytes32 role, address account) external; function revokeRole(bytes32 role, address account) external; function setFRAXAddress(address frax_contract_address) external; function setFXSMinDAO(uint256 min_FXS) external; function setOracle(address new_oracle) external; function setOwner(address _owner_address) external; function setTimelock(address new_timelock) external; function symbol() external view returns(string memory); function timelock_address() external view returns(address); function toggleVotes() external; function totalSupply() external view returns(uint256); function trackingVotes() external view returns(bool); function transfer(address recipient, uint256 amount) external returns(bool); function transferFrom(address sender, address recipient, uint256 amount) external returns(bool); } // File contracts/Frax/IFraxAMOMinter.sol // MAY need to be updated interface IFraxAMOMinter { function FRAX() external view returns(address); function FXS() external view returns(address); function acceptOwnership() external; function addAMO(address amo_address, bool sync_too) external; function allAMOAddresses() external view returns(address[] memory); function allAMOsLength() external view returns(uint256); function amos(address) external view returns(bool); function amos_array(uint256) external view returns(address); function burnFraxFromAMO(uint256 frax_amount) external; function burnFxsFromAMO(uint256 fxs_amount) external; function col_idx() external view returns(uint256); function collatDollarBalance() external view returns(uint256); function collatDollarBalanceStored() external view returns(uint256); function collat_borrow_cap() external view returns(int256); function collat_borrowed_balances(address) external view returns(int256); function collat_borrowed_sum() external view returns(int256); function collateral_address() external view returns(address); function collateral_token() external view returns(address); function correction_offsets_amos(address, uint256) external view returns(int256); function custodian_address() external view returns(address); function dollarBalances() external view returns(uint256 frax_val_e18, uint256 collat_val_e18); // function execute(address _to, uint256 _value, bytes _data) external returns(bool, bytes); function fraxDollarBalanceStored() external view returns(uint256); function fraxTrackedAMO(address amo_address) external view returns(int256); function fraxTrackedGlobal() external view returns(int256); function frax_mint_balances(address) external view returns(int256); function frax_mint_cap() external view returns(int256); function frax_mint_sum() external view returns(int256); function fxs_mint_balances(address) external view returns(int256); function fxs_mint_cap() external view returns(int256); function fxs_mint_sum() external view returns(int256); function giveCollatToAMO(address destination_amo, uint256 collat_amount) external; function min_cr() external view returns(uint256); function mintFraxForAMO(address destination_amo, uint256 frax_amount) external; function mintFxsForAMO(address destination_amo, uint256 fxs_amount) external; function missing_decimals() external view returns(uint256); function nominateNewOwner(address _owner) external; function nominatedOwner() external view returns(address); function oldPoolCollectAndGive(address destination_amo) external; function oldPoolRedeem(uint256 frax_amount) external; function old_pool() external view returns(address); function owner() external view returns(address); function pool() external view returns(address); function receiveCollatFromAMO(uint256 usdc_amount) external; function recoverERC20(address tokenAddress, uint256 tokenAmount) external; function removeAMO(address amo_address, bool sync_too) external; function setAMOCorrectionOffsets(address amo_address, int256 frax_e18_correction, int256 collat_e18_correction) external; function setCollatBorrowCap(uint256 _collat_borrow_cap) external; function setCustodian(address _custodian_address) external; function setFraxMintCap(uint256 _frax_mint_cap) external; function setFraxPool(address _pool_address) external; function setFxsMintCap(uint256 _fxs_mint_cap) external; function setMinimumCollateralRatio(uint256 _min_cr) external; function setTimelock(address new_timelock) external; function syncDollarBalances() external; function timelock_address() external view returns(address); } // File contracts/Staking/Owned.sol // https://docs.synthetix.io/contracts/Owned contract Owned { address public owner; address public nominatedOwner; constructor (address _owner) public { require(_owner != address(0), "Owner address cannot be 0"); owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } modifier onlyOwner { require(msg.sender == owner, "Only the contract owner may perform this action"); _; } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); } // File contracts/Math/Math.sol /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } } // File contracts/Math/SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File contracts/Curve/IveFXS.sol pragma abicoder v2; interface IveFXS { struct LockedBalance { int128 amount; uint256 end; } function commit_transfer_ownership(address addr) external; function apply_transfer_ownership() external; function commit_smart_wallet_checker(address addr) external; function apply_smart_wallet_checker() external; function toggleEmergencyUnlock() external; function recoverERC20(address token_addr, uint256 amount) external; function get_last_user_slope(address addr) external view returns (int128); function user_point_history__ts(address _addr, uint256 _idx) external view returns (uint256); function locked__end(address _addr) external view returns (uint256); function checkpoint() external; function deposit_for(address _addr, uint256 _value) external; function create_lock(uint256 _value, uint256 _unlock_time) external; function increase_amount(uint256 _value) external; function increase_unlock_time(uint256 _unlock_time) external; function withdraw() external; function balanceOf(address addr) external view returns (uint256); function balanceOf(address addr, uint256 _t) external view returns (uint256); function balanceOfAt(address addr, uint256 _block) external view returns (uint256); function totalSupply() external view returns (uint256); function totalSupply(uint256 t) external view returns (uint256); function totalSupplyAt(uint256 _block) external view returns (uint256); function totalFXSSupply() external view returns (uint256); function totalFXSSupplyAt(uint256 _block) external view returns (uint256); function changeController(address _newController) external; function token() external view returns (address); function supply() external view returns (uint256); function locked(address addr) external view returns (LockedBalance memory); function epoch() external view returns (uint256); function point_history(uint256 arg0) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt); function user_point_history(address arg0, uint256 arg1) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt); function user_point_epoch(address arg0) external view returns (uint256); function slope_changes(uint256 arg0) external view returns (int128); function controller() external view returns (address); function transfersEnabled() external view returns (bool); function emergencyUnlockActive() external view returns (bool); function name() external view returns (string memory); function symbol() external view returns (string memory); function version() external view returns (string memory); function decimals() external view returns (uint256); function future_smart_wallet_checker() external view returns (address); function smart_wallet_checker() external view returns (address); function admin() external view returns (address); function future_admin() external view returns (address); } // File contracts/Uniswap/TransferHelper.sol // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); } function safeTransfer(address token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); } function safeTransferFrom(address token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); } function safeTransferETH(address to, uint value) internal { (bool success,) = to.call{value:value}(new bytes(0)); require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); } } // File contracts/Common/Context.sol /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return payable(msg.sender); } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File contracts/ERC20/IERC20.sol /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ 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); } // File contracts/Utils/Address.sol /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File contracts/ERC20/ERC20.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}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * 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. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory __name, string memory __symbol) public { _name = __name; _symbol = __symbol; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address.approve(address spender, uint256 amount) */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @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: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for `accounts`'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance"); _approve(account, _msgSender(), decreasedAllowance); _burn(account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal virtual { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of `from`'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of `from`'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File contracts/ERC20/SafeERC20.sol /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File contracts/Utils/ReentrancyGuard.sol /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File contracts/Staking/veFXSYieldDistributorV4.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ======================veFXSYieldDistributorV4======================= // ==================================================================== // Distributes Frax protocol yield based on the claimer's veFXS balance // V3: Yield will now not accrue for unlocked veFXS // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Travis Moore: https://github.com/FortisFortuna // Reviewer(s) / Contributor(s) // Jason Huan: https://github.com/jasonhuan // Sam Kazemian: https://github.com/samkazemian // Originally inspired by Synthetix.io, but heavily modified by the Frax team (veFXS portion) // https://github.com/Synthetixio/synthetix/blob/develop/contracts/StakingRewards.sol contract veFXSYieldDistributorV4 is Owned, ReentrancyGuard { using SafeMath for uint256; using SafeERC20 for ERC20; /* ========== STATE VARIABLES ========== */ // Instances IveFXS private veFXS; ERC20 public emittedToken; // Addresses address public emitted_token_address; // Admin addresses address public timelock_address; // Constant for price precision uint256 private constant PRICE_PRECISION = 1e6; // Yield and period related uint256 public periodFinish; uint256 public lastUpdateTime; uint256 public yieldRate; uint256 public yieldDuration = 604800; // 7 * 86400 (7 days) mapping(address => bool) public reward_notifiers; // Yield tracking uint256 public yieldPerVeFXSStored = 0; mapping(address => uint256) public userYieldPerTokenPaid; mapping(address => uint256) public yields; // veFXS tracking uint256 public totalVeFXSParticipating = 0; uint256 public totalVeFXSSupplyStored = 0; mapping(address => bool) public userIsInitialized; mapping(address => uint256) public userVeFXSCheckpointed; mapping(address => uint256) public userVeFXSEndpointCheckpointed; mapping(address => uint256) private lastRewardClaimTime; // staker addr -> timestamp // Greylists mapping(address => bool) public greylist; // Admin booleans for emergencies bool public yieldCollectionPaused = false; // For emergencies struct LockedBalance { int128 amount; uint256 end; } /* ========== MODIFIERS ========== */ modifier onlyByOwnGov() { require( msg.sender == owner || msg.sender == timelock_address, "Not owner or timelock"); _; } modifier notYieldCollectionPaused() { require(yieldCollectionPaused == false, "Yield collection is paused"); _; } modifier checkpointUser(address account) { _checkpointUser(account); _; } /* ========== CONSTRUCTOR ========== */ constructor ( address _owner, address _emittedToken, address _timelock_address, address _veFXS_address ) Owned(_owner) { emitted_token_address = _emittedToken; emittedToken = ERC20(_emittedToken); veFXS = IveFXS(_veFXS_address); lastUpdateTime = block.timestamp; timelock_address = _timelock_address; reward_notifiers[_owner] = true; } /* ========== VIEWS ========== */ function fractionParticipating() external view returns (uint256) { return totalVeFXSParticipating.mul(PRICE_PRECISION).div(totalVeFXSSupplyStored); } // Only positions with locked veFXS can accrue yield. Otherwise, expired-locked veFXS // is de-facto rewards for FXS. function eligibleCurrentVeFXS(address account) public view returns (uint256 eligible_vefxs_bal, uint256 stored_ending_timestamp) { uint256 curr_vefxs_bal = veFXS.balanceOf(account); // Stored is used to prevent abuse stored_ending_timestamp = userVeFXSEndpointCheckpointed[account]; // Only unexpired veFXS should be eligible if (stored_ending_timestamp != 0 && (block.timestamp >= stored_ending_timestamp)){ eligible_vefxs_bal = 0; } else if (block.timestamp >= stored_ending_timestamp){ eligible_vefxs_bal = 0; } else { eligible_vefxs_bal = curr_vefxs_bal; } } function lastTimeYieldApplicable() public view returns (uint256) { return Math.min(block.timestamp, periodFinish); } function yieldPerVeFXS() public view returns (uint256) { if (totalVeFXSSupplyStored == 0) { return yieldPerVeFXSStored; } else { return ( yieldPerVeFXSStored.add( lastTimeYieldApplicable() .sub(lastUpdateTime) .mul(yieldRate) .mul(1e18) .div(totalVeFXSSupplyStored) ) ); } } function earned(address account) public view returns (uint256) { // Uninitialized users should not earn anything yet if (!userIsInitialized[account]) return 0; // Get eligible veFXS balances (uint256 eligible_current_vefxs, uint256 ending_timestamp) = eligibleCurrentVeFXS(account); // If your veFXS is unlocked uint256 eligible_time_fraction = PRICE_PRECISION; if (eligible_current_vefxs == 0){ // And you already claimed after expiration if (lastRewardClaimTime[account] >= ending_timestamp) { // You get NOTHING. You LOSE. Good DAY ser! return 0; } // You haven't claimed yet else { uint256 eligible_time = (ending_timestamp).sub(lastRewardClaimTime[account]); uint256 total_time = (block.timestamp).sub(lastRewardClaimTime[account]); eligible_time_fraction = PRICE_PRECISION.mul(eligible_time).div(total_time); } } // If the amount of veFXS increased, only pay off based on the old balance // Otherwise, take the midpoint uint256 vefxs_balance_to_use; { uint256 old_vefxs_balance = userVeFXSCheckpointed[account]; if (eligible_current_vefxs > old_vefxs_balance){ vefxs_balance_to_use = old_vefxs_balance; } else { vefxs_balance_to_use = ((eligible_current_vefxs).add(old_vefxs_balance)).div(2); } } return ( vefxs_balance_to_use .mul(yieldPerVeFXS().sub(userYieldPerTokenPaid[account])) .mul(eligible_time_fraction) .div(1e18 * PRICE_PRECISION) .add(yields[account]) ); } function getYieldForDuration() external view returns (uint256) { return (yieldRate.mul(yieldDuration)); } /* ========== MUTATIVE FUNCTIONS ========== */ function _checkpointUser(address account) internal { // Need to retro-adjust some things if the period hasn't been renewed, then start a new one sync(); // Calculate the earnings first _syncEarned(account); // Get the old and the new veFXS balances uint256 old_vefxs_balance = userVeFXSCheckpointed[account]; uint256 new_vefxs_balance = veFXS.balanceOf(account); // Update the user's stored veFXS balance userVeFXSCheckpointed[account] = new_vefxs_balance; // Update the user's stored ending timestamp IveFXS.LockedBalance memory curr_locked_bal_pack = veFXS.locked(account); userVeFXSEndpointCheckpointed[account] = curr_locked_bal_pack.end; // Update the total amount participating if (new_vefxs_balance >= old_vefxs_balance) { uint256 weight_diff = new_vefxs_balance.sub(old_vefxs_balance); totalVeFXSParticipating = totalVeFXSParticipating.add(weight_diff); } else { uint256 weight_diff = old_vefxs_balance.sub(new_vefxs_balance); totalVeFXSParticipating = totalVeFXSParticipating.sub(weight_diff); } // Mark the user as initialized if (!userIsInitialized[account]) { userIsInitialized[account] = true; lastRewardClaimTime[account] = block.timestamp; } } function _syncEarned(address account) internal { if (account != address(0)) { uint256 earned0 = earned(account); yields[account] = earned0; userYieldPerTokenPaid[account] = yieldPerVeFXSStored; } } // Anyone can checkpoint another user function checkpointOtherUser(address user_addr) external { _checkpointUser(user_addr); } // Checkpoints the user function checkpoint() external { _checkpointUser(msg.sender); } function getYield() external nonReentrant notYieldCollectionPaused checkpointUser(msg.sender) returns (uint256 yield0) { require(greylist[msg.sender] == false, "Address has been greylisted"); yield0 = yields[msg.sender]; if (yield0 > 0) { yields[msg.sender] = 0; TransferHelper.safeTransfer( emitted_token_address, msg.sender, yield0 ); emit YieldCollected(msg.sender, yield0, emitted_token_address); } lastRewardClaimTime[msg.sender] = block.timestamp; } function sync() public { // Update the total veFXS supply yieldPerVeFXSStored = yieldPerVeFXS(); totalVeFXSSupplyStored = veFXS.totalSupply(); lastUpdateTime = lastTimeYieldApplicable(); } function notifyRewardAmount(uint256 amount) external { // Only whitelisted addresses can notify rewards require(reward_notifiers[msg.sender], "Sender not whitelisted"); // Handle the transfer of emission tokens via `transferFrom` to reduce the number // of transactions required and ensure correctness of the smission amount emittedToken.safeTransferFrom(msg.sender, address(this), amount); // Update some values beforehand sync(); // Update the new yieldRate if (block.timestamp >= periodFinish) { yieldRate = amount.div(yieldDuration); } else { uint256 remaining = periodFinish.sub(block.timestamp); uint256 leftover = remaining.mul(yieldRate); yieldRate = amount.add(leftover).div(yieldDuration); } // Update duration-related info lastUpdateTime = block.timestamp; periodFinish = block.timestamp.add(yieldDuration); emit RewardAdded(amount, yieldRate); } /* ========== RESTRICTED FUNCTIONS ========== */ // Added to support recovering LP Yield and other mistaken tokens from other systems to be distributed to holders function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyByOwnGov { // Only the owner address can ever receive the recovery withdrawal TransferHelper.safeTransfer(tokenAddress, owner, tokenAmount); emit RecoveredERC20(tokenAddress, tokenAmount); } function setYieldDuration(uint256 _yieldDuration) external onlyByOwnGov { require( periodFinish == 0 || block.timestamp > periodFinish, "Previous yield period must be complete before changing the duration for the new period"); yieldDuration = _yieldDuration; emit YieldDurationUpdated(yieldDuration); } function greylistAddress(address _address) external onlyByOwnGov { greylist[_address] = !(greylist[_address]); } function toggleRewardNotifier(address notifier_addr) external onlyByOwnGov { reward_notifiers[notifier_addr] = !reward_notifiers[notifier_addr]; } function setPauses(bool _yieldCollectionPaused) external onlyByOwnGov { yieldCollectionPaused = _yieldCollectionPaused; } function setYieldRate(uint256 _new_rate0, bool sync_too) external onlyByOwnGov { yieldRate = _new_rate0; if (sync_too) { sync(); } } function setTimelock(address _new_timelock) external onlyByOwnGov { timelock_address = _new_timelock; } /* ========== EVENTS ========== */ event RewardAdded(uint256 reward, uint256 yieldRate); event OldYieldCollected(address indexed user, uint256 yield, address token_address); event YieldCollected(address indexed user, uint256 yield, address token_address); event YieldDurationUpdated(uint256 newDuration); event RecoveredERC20(address token, uint256 amount); event YieldPeriodRenewed(address token, uint256 yieldRate); event DefaultInitialization(); /* ========== A CHICKEN ========== */ // // ,~. // ,-'__ `-, // {,-' `. } ,') // ,( a ) `-.__ ,',')~, // <=.) ( `-.__,==' ' ' '} // ( ) /) // `-'\ , ) // | \ `~. / // \ `._ \ / // \ `._____,' ,' // `-. ,' // `-._ _,-' // 77jj' // //_|| // __//--'/` // ,--'/` ' // // [hjw] https://textart.io/art/vw6Sa3iwqIRGkZsN1BC2vweF/chicken } // File contracts/Oracle/AggregatorV3Interface.sol interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File contracts/Fraxswap/core/interfaces/IUniswapV2PairV5.sol interface IUniswapV2PairV5 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; } // File contracts/Fraxswap/core/interfaces/IFraxswapPair.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ========================= IFraxswapPair ========================== // ==================================================================== // Fraxswap LP Pair Interface // Inspired by https://www.paradigm.xyz/2021/07/twamm // https://github.com/para-dave/twamm // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Rich Gee: https://github.com/zer0blockchain // Dennis: https://github.com/denett // Reviewer(s) / Contributor(s) // Travis Moore: https://github.com/FortisFortuna // Sam Kazemian: https://github.com/samkazemian interface IFraxswapPair is IUniswapV2PairV5 { // TWAMM event LongTermSwap0To1(address indexed addr, uint256 orderId, uint256 amount0In, uint256 numberOfTimeIntervals); event LongTermSwap1To0(address indexed addr, uint256 orderId, uint256 amount1In, uint256 numberOfTimeIntervals); event CancelLongTermOrder(address indexed addr, uint256 orderId, address sellToken, uint256 unsoldAmount, address buyToken, uint256 purchasedAmount); event WithdrawProceedsFromLongTermOrder(address indexed addr, uint256 orderId, address indexed proceedToken, uint256 proceeds, bool orderExpired); function longTermSwapFrom0To1(uint256 amount0In, uint256 numberOfTimeIntervals) external returns (uint256 orderId); function longTermSwapFrom1To0(uint256 amount1In, uint256 numberOfTimeIntervals) external returns (uint256 orderId); function cancelLongTermSwap(uint256 orderId) external; function withdrawProceedsFromLongTermSwap(uint256 orderId) external returns (bool is_expired, address rewardTkn, uint256 totalReward); function executeVirtualOrders(uint256 blockTimestamp) external; function orderTimeInterval() external returns (uint256); function getTWAPHistoryLength() external view returns (uint); function getTwammReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast, uint112 _twammReserve0, uint112 _twammReserve1); function getReserveAfterTwamm(uint256 blockTimestamp) external view returns (uint112 _reserve0, uint112 _reserve1, uint256 lastVirtualOrderTimestamp, uint112 _twammReserve0, uint112 _twammReserve1); function getNextOrderID() external view returns (uint256); function getOrderIDsForUser(address user) external view returns (uint256[] memory); function getOrderIDsForUserLength(address user) external view returns (uint256); // function getDetailedOrdersForUser(address user, uint256 offset, uint256 limit) external view returns (LongTermOrdersLib.Order[] memory detailed_orders); function twammUpToDate() external view returns (bool); function getTwammState() external view returns (uint256 token0Rate, uint256 token1Rate, uint256 lastVirtualOrderTimestamp, uint256 orderTimeInterval_rtn, uint256 rewardFactorPool0, uint256 rewardFactorPool1); function getTwammSalesRateEnding(uint256 _blockTimestamp) external view returns (uint256 orderPool0SalesRateEnding, uint256 orderPool1SalesRateEnding); function getTwammRewardFactor(uint256 _blockTimestamp) external view returns (uint256 rewardFactorPool0AtTimestamp, uint256 rewardFactorPool1AtTimestamp); function getTwammOrder(uint256 orderId) external view returns (uint256 id, uint256 expirationTimestamp, uint256 saleRate, address owner, address sellTokenAddr, address buyTokenAddr); function getTwammOrderProceedsView(uint256 orderId, uint256 blockTimestamp) external view returns (bool orderExpired, uint256 totalReward); function getTwammOrderProceeds(uint256 orderId) external returns (bool orderExpired, uint256 totalReward); function togglePauseNewSwaps() external; } // File contracts/Fraxswap/core/interfaces/IUniswapV2FactoryV5.sol interface IUniswapV2FactoryV5 { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; } // File contracts/Fraxswap/libraries/Babylonian.sol // computes square roots using the babylonian method // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method library Babylonian { // credit for this implementation goes to // https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol#L687 function sqrt(uint256 x) internal pure returns (uint256) { if (x == 0) return 0; // this block is equivalent to r = uint256(1) << (BitMath.mostSignificantBit(x) / 2); // however that code costs significantly more gas 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 (r < r1 ? r : r1); } } // File contracts/Fraxswap/libraries/FullMath.sol /// @notice Math library that facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision. /// @author Adapted from https://github.com/Uniswap/uniswap-v3-core/blob/main/contracts/libraries/FullMath.sol. /// @dev Handles "phantom overflow", i.e., allows multiplication and division where an intermediate value overflows 256 bits. library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision - throws if result overflows an uint256 or denominator == 0. /// @param a The multiplicand. /// @param b The multiplier. /// @param denominator The divisor. /// @return result The 256-bit result. /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv. function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b. // Compute the product mod 2**256 and mod 2**256 - 1, // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0. uint256 prod0; // Least significant 256 bits of the product. uint256 prod1; // Most significant 256 bits of the product. assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256 - // also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] - // compute remainder using mulmod. uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number. assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator - // compute largest power of two divisor of denominator // (always >= 1). uint256 twos = uint256(-int256(denominator)) & denominator; // Divide denominator by power of two. assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two. assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos - // if twos is zero, then it becomes one. assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 - // now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // for four bits. That is, denominator * inv = 1 mod 2**4. uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // Inverse mod 2**8. inv *= 2 - denominator * inv; // Inverse mod 2**16. inv *= 2 - denominator * inv; // Inverse mod 2**32. inv *= 2 - denominator * inv; // Inverse mod 2**64. inv *= 2 - denominator * inv; // Inverse mod 2**128. inv *= 2 - denominator * inv; // Inverse mod 2**256. // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision - throws if result overflows an uint256 or denominator == 0. /// @param a The multiplicand. /// @param b The multiplier. /// @param denominator The divisor. /// @return result The 256-bit result. function mulDivRoundingUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { result = mulDiv(a, b, denominator); unchecked { if (mulmod(a, b, denominator) != 0) { require(result < type(uint256).max); result++; } } } } // File contracts/Fraxswap/periphery/libraries/UniswapV2LiquidityMathLibraryMini.sol // library containing some math for dealing with the liquidity shares of a pair, e.g. computing their exact value // in terms of the underlying tokens library UniswapV2LiquidityMathLibraryMini { // computes the direction and magnitude of the profit-maximizing trade // function computeProfitMaximizingTrade( // uint256 truePriceTokenA, // uint256 truePriceTokenB, // uint256 reserveA, // uint256 reserveB // ) pure internal returns (uint256 amountIn) { // bool aToB = ((reserveA * truePriceTokenB) / reserveB) < truePriceTokenA; // uint256 invariant = reserveA * reserveB; // // true price is expressed as a ratio, so both values must be non-zero // require(truePriceTokenA != 0 && truePriceTokenB != 0, "CPMT: ZERO_PRICE"); // uint256 leftSide = Babylonian.sqrt( // FullMath.mulDiv( // (invariant * 1000), // aToB ? truePriceTokenA : truePriceTokenB, // (aToB ? truePriceTokenB : truePriceTokenA) * 997 // ) // ); // uint256 rightSide = (aToB ? reserveA * 1000 : reserveB * 1000) / 997; // if (leftSide < rightSide) return (0); // // compute the amount that must be sent to move the price to the profit-maximizing price // amountIn = leftSide - rightSide; // } function computeProfitMaximizingTrade( uint256 inTokenTruePrice, uint256 outTokenTruePrice, uint256 reserveIn, uint256 reserveOut ) pure internal returns (uint256 amountIn) { uint256 invariant = reserveIn * reserveOut; // true price is expressed as a ratio, so both values must be non-zero require(inTokenTruePrice != 0 && outTokenTruePrice != 0, "CPMT: ZERO_PRICE"); uint256 leftSide = Babylonian.sqrt( FullMath.mulDiv( (invariant * 1000), inTokenTruePrice, outTokenTruePrice * 997 ) ); uint256 rightSide = (reserveIn * 1000) / 997; if (leftSide < rightSide) return (0); // compute the amount that must be sent to move the price to the profit-maximizing price amountIn = leftSide - rightSide; } } // File contracts/Misc_AMOs/TWAMM_AMO.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ============================ TWAMM_AMO ============================= // ==================================================================== // Interacts with Fraxswap to buy and sell FRAX and FXS // Also can burn them or in the case of FXS, give to veFXS yield // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Travis Moore: https://github.com/FortisFortuna // Reviewer(s) / Contributor(s) // Sam Kazemian: https://github.com/samkazemian // Rich Gee: https://github.com/zer0blockchain // Dennis: https://github.com/denett // Jack Corddry: https://github.com/corddry contract TWAMM_AMO is Owned { // Core IFrax public FRAX; IFxs public FXS; IFraxswapPair public fraxswap_pair; IFraxAMOMinter public amo_minter; veFXSYieldDistributorV4 public yield_distributor; address public timelock_address; address public msig_address; // Oracles AggregatorV3Interface public priceFeedFRAXUSD; AggregatorV3Interface public priceFeedFXSUSD; uint256 public chainlink_frax_usd_decimals; uint256 public chainlink_fxs_usd_decimals; // Safety uint256 public max_swap_frax_amt_in = 10000000e18; // 10M, mainly fat-finger precautions uint256 public max_swap_fxs_amt_in = 10000000e18; // 10M, mainly fat-finger precautions // Constants for various precisions uint256 public constant PRICE_PRECISION = 1e18; // Misc bool public frax_is_token0; uint256 public num_twamm_intervals = 168; // Each interval is default 3600 sec (1 hr) uint256 public swap_period = 7 * 86400; // 7 days /* ========== MODIFIERS ========== */ modifier onlyByOwnGov() { require(msg.sender == owner || msg.sender == timelock_address, "Not owner or timelock"); _; } /* ========== CONSTRUCTOR ========== */ constructor ( address _creator_address, address _timelock_address, address[8] memory _address_pack ) Owned(_creator_address) { // Set timelock timelock_address = _timelock_address; // Set instances FRAX = IFrax(_address_pack[0]); FXS = IFxs(_address_pack[1]); fraxswap_pair = IFraxswapPair(_address_pack[2]); priceFeedFRAXUSD = AggregatorV3Interface(_address_pack[3]); priceFeedFXSUSD = AggregatorV3Interface(_address_pack[4]); msig_address = _address_pack[5]; amo_minter = IFraxAMOMinter(_address_pack[6]); yield_distributor = veFXSYieldDistributorV4(_address_pack[7]); // Set the oracle decimals chainlink_frax_usd_decimals = priceFeedFRAXUSD.decimals(); chainlink_fxs_usd_decimals = priceFeedFXSUSD.decimals(); // Need to know which token FRAX is (0 or 1) address token0 = fraxswap_pair.token0(); if (token0 == address(FRAX)) frax_is_token0 = true; else frax_is_token0 = false; // Get the number of TWAMM intervals. Truncation desired num_twamm_intervals = swap_period / fraxswap_pair.orderTimeInterval(); } /* ========== VIEWS ========== */ // Needed as a FRAX AMO function dollarBalances() public view returns (uint256 frax_val_e18, uint256 collat_val_e18) { frax_val_e18 = FRAX.balanceOf(address(this)); // Unallocated FRAX collat_val_e18 = (frax_val_e18 * FRAX.global_collateral_ratio()) / 1e6; } // In Chainlink decimals function getFRAXPriceE18() public view returns (uint256) { (uint80 roundID, int price, , uint256 updatedAt, uint80 answeredInRound) = priceFeedFRAXUSD.latestRoundData(); require(price >= 0 && updatedAt!= 0 && answeredInRound >= roundID, "Invalid chainlink price"); return ((uint256(price) * 1e18) / (10 ** chainlink_frax_usd_decimals)); } // In Chainlink decimals function getFXSPriceE18() public view returns (uint256) { (uint80 roundID, int price, , uint256 updatedAt, uint80 answeredInRound) = priceFeedFXSUSD.latestRoundData(); require(price >= 0 && updatedAt!= 0 && answeredInRound >= roundID, "Invalid chainlink price"); return ((uint256(price) * 1e18) / (10 ** chainlink_fxs_usd_decimals)); } /* ========== MUTATIVE ========== */ // Use the TWAMM function twammSwap(uint256 frax_sell_amt, uint256 fxs_sell_amount, uint256 override_intervals) external onlyByOwnGov returns (uint256 frax_to_use, uint256 fxs_to_use, uint256 new_order_id) { // Make sure only one direction occurs require(!((frax_sell_amt > 0) && (fxs_sell_amount > 0)), "Can only sell in one direction"); { if (fxs_sell_amount > 0) { // Sell FXS for FRAX // -------------------------------- fxs_to_use = fxs_sell_amount; // Make sure nonzero require(fxs_to_use > 0, "FXS sold must be nonzero"); // Safety check require(fxs_to_use <= max_swap_fxs_amt_in, "Too much FXS sold"); // Approve FXS first FXS.approve(address(fraxswap_pair), fxs_to_use); // Swap if (frax_is_token0) { new_order_id = fraxswap_pair.longTermSwapFrom1To0(fxs_to_use, override_intervals > 0 ? override_intervals : num_twamm_intervals); } else { new_order_id = fraxswap_pair.longTermSwapFrom0To1(fxs_to_use, override_intervals > 0 ? override_intervals : num_twamm_intervals); } } else { // Use FRAX to buy FXS // -------------------------------- frax_to_use = frax_sell_amt; // Make sure nonzero require(frax_to_use > 0, "FRAX sold must be nonzero"); // Safety check require(frax_to_use <= max_swap_frax_amt_in, "Too much FRAX sold"); // Approve FRAX first FRAX.approve(address(fraxswap_pair), frax_to_use); // Swap if (frax_is_token0) { new_order_id = fraxswap_pair.longTermSwapFrom0To1(frax_to_use, override_intervals > 0 ? override_intervals : num_twamm_intervals); } else { new_order_id = fraxswap_pair.longTermSwapFrom1To0(frax_to_use, override_intervals > 0 ? override_intervals : num_twamm_intervals); } } } emit SwapInitiated(new_order_id, frax_to_use, fxs_to_use, block.timestamp); } function cancelTWAMMOrder(uint256 order_id) external onlyByOwnGov { // Cancel the order fraxswap_pair.cancelLongTermSwap(order_id); emit SwapCancelled(order_id); } function collectCurrTWAMMProceeds(uint256 order_id) external onlyByOwnGov { // Withdraw current proceeds (, address rewardTkn, uint256 totalReward) = fraxswap_pair.withdrawProceedsFromLongTermSwap(order_id); emit SwapProceedsCollected(order_id, rewardTkn, totalReward); } // token_choice 0 = FRAX; 1 = FXS function burnAndOrGive( uint8 token_choice, uint256 burn_amount, uint256 give_amount_yield_dist, uint256 give_amount_msig ) external onlyByOwnGov { if (token_choice == 0) { // Burn some of the FRAX if (burn_amount > 0) burnFRAX(burn_amount); // Give the rest to the yield distributor // NOT APPLICABLE FOR FRAX // Give some to the msig if (give_amount_msig > 0) TransferHelper.safeTransfer(address(FRAX), msig_address, give_amount_msig); } else { // Burn some of the FXS if (burn_amount > 0) burnFXS(burn_amount); // Give some to the yield distributor if (give_amount_yield_dist > 0) { FXS.approve(address(yield_distributor), give_amount_yield_dist); yield_distributor.notifyRewardAmount(give_amount_yield_dist); } // Give some to the msig if (give_amount_msig > 0) TransferHelper.safeTransfer(address(FXS), msig_address, give_amount_msig); } emit burnAndOrGiven(token_choice, burn_amount, give_amount_yield_dist, give_amount_msig); } /* ========== Burns and givebacks ========== */ // Burn unneeded or excess FRAX. Goes through the minter function burnFRAX(uint256 frax_amount) public onlyByOwnGov { FRAX.approve(address(amo_minter), frax_amount); amo_minter.burnFraxFromAMO(frax_amount); emit FRAXBurned(frax_amount); } // Burn unneeded FXS. Goes through the minter function burnFXS(uint256 fxs_amount) public onlyByOwnGov { FXS.approve(address(amo_minter), fxs_amount); amo_minter.burnFxsFromAMO(fxs_amount); emit FXSBurned(fxs_amount); } /* ========== RESTRICTED FUNCTIONS ========== */ function setOracles(address _frax_oracle, address _fxs_oracle) external onlyByOwnGov { priceFeedFRAXUSD = AggregatorV3Interface(_frax_oracle); priceFeedFXSUSD = AggregatorV3Interface(_fxs_oracle); // Set the Chainlink oracle decimals chainlink_frax_usd_decimals = priceFeedFRAXUSD.decimals(); chainlink_fxs_usd_decimals = priceFeedFXSUSD.decimals(); } function setTWAMMAndSwapPeriod(address _twamm_addr, uint256 _swap_period) external onlyByOwnGov { // Change the TWAMM parameters fraxswap_pair = IFraxswapPair(_twamm_addr); swap_period = _swap_period; num_twamm_intervals = _swap_period / fraxswap_pair.orderTimeInterval(); } function setTWAMMMaxSwapIn(uint256 _max_swap_frax_amt_in, uint256 _max_swap_fxs_amt_in) external onlyByOwnGov { max_swap_frax_amt_in = _max_swap_frax_amt_in; max_swap_fxs_amt_in = _max_swap_fxs_amt_in; } function setMiscAddresses(address _new_msig_address, address _new_yield_distributor_address) external onlyByOwnGov { msig_address = _new_msig_address; yield_distributor = veFXSYieldDistributorV4(_new_yield_distributor_address); } function setTimelock(address _new_timelock_address) external onlyByOwnGov { timelock_address = _new_timelock_address; } // Added to support recovering LP Rewards and other mistaken tokens from other systems to be distributed to holders function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyByOwnGov { // Only the owner address can ever receive the recovery withdrawal TransferHelper.safeTransfer(tokenAddress, owner, tokenAmount); emit RecoveredERC20(tokenAddress, tokenAmount); } /* ========== EVENTS ========== */ event SwapInitiated(uint256 order_id, uint256 frax_amt, uint256 fxs_amt, uint256 timestamp); event SwapCancelled(uint256 order_id); event SwapProceedsCollected(uint256 order_id, address reward_tkn, uint256 ttl_reward); event burnAndOrGiven(uint8 token_choice, uint256 burn_amount, uint256 give_amount_yield_dist, uint256 give_amount_msig); event FRAXBurned(uint256 frax_amount); event FXSBurned(uint256 fxs_amount); event RecoveredERC20(address token, uint256 amount); }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_creator_address","type":"address"},{"internalType":"address","name":"_timelock_address","type":"address"},{"internalType":"address[8]","name":"_address_pack","type":"address[8]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"FRAXBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fxs_amount","type":"uint256"}],"name":"FXSBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RecoveredERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"order_id","type":"uint256"}],"name":"SwapCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"order_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"frax_amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fxs_amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SwapInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"order_id","type":"uint256"},{"indexed":false,"internalType":"address","name":"reward_tkn","type":"address"},{"indexed":false,"internalType":"uint256","name":"ttl_reward","type":"uint256"}],"name":"SwapProceedsCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"token_choice","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"burn_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"give_amount_yield_dist","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"give_amount_msig","type":"uint256"}],"name":"burnAndOrGiven","type":"event"},{"inputs":[],"name":"FRAX","outputs":[{"internalType":"contract IFrax","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FXS","outputs":[{"internalType":"contract IFxs","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"amo_minter","outputs":[{"internalType":"contract IFraxAMOMinter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"token_choice","type":"uint8"},{"internalType":"uint256","name":"burn_amount","type":"uint256"},{"internalType":"uint256","name":"give_amount_yield_dist","type":"uint256"},{"internalType":"uint256","name":"give_amount_msig","type":"uint256"}],"name":"burnAndOrGive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"burnFRAX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fxs_amount","type":"uint256"}],"name":"burnFXS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"order_id","type":"uint256"}],"name":"cancelTWAMMOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainlink_frax_usd_decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainlink_fxs_usd_decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"order_id","type":"uint256"}],"name":"collectCurrTWAMMProceeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dollarBalances","outputs":[{"internalType":"uint256","name":"frax_val_e18","type":"uint256"},{"internalType":"uint256","name":"collat_val_e18","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"frax_is_token0","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxswap_pair","outputs":[{"internalType":"contract IFraxswapPair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFRAXPriceE18","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFXSPriceE18","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"max_swap_frax_amt_in","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"max_swap_fxs_amt_in","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"msig_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"num_twamm_intervals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedFRAXUSD","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedFXSUSD","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_new_msig_address","type":"address"},{"internalType":"address","name":"_new_yield_distributor_address","type":"address"}],"name":"setMiscAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_frax_oracle","type":"address"},{"internalType":"address","name":"_fxs_oracle","type":"address"}],"name":"setOracles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_twamm_addr","type":"address"},{"internalType":"uint256","name":"_swap_period","type":"uint256"}],"name":"setTWAMMAndSwapPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_max_swap_frax_amt_in","type":"uint256"},{"internalType":"uint256","name":"_max_swap_fxs_amt_in","type":"uint256"}],"name":"setTWAMMMaxSwapIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_new_timelock_address","type":"address"}],"name":"setTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swap_period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelock_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"frax_sell_amt","type":"uint256"},{"internalType":"uint256","name":"fxs_sell_amount","type":"uint256"},{"internalType":"uint256","name":"override_intervals","type":"uint256"}],"name":"twammSwap","outputs":[{"internalType":"uint256","name":"frax_to_use","type":"uint256"},{"internalType":"uint256","name":"fxs_to_use","type":"uint256"},{"internalType":"uint256","name":"new_order_id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"yield_distributor","outputs":[{"internalType":"contract veFXSYieldDistributorV4","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040526a084595161401484a000000600d556a084595161401484a000000600e5560a860105562093a806011553480156200003b57600080fd5b5060405162002e9f38038062002e9f8339810160408190526200005e9162000413565b826001600160a01b038116620000ba5760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150600780546001600160a01b03199081166001600160a01b03858116919091179092558251600280548316918416919091179055602080840151600380548416918516919091179055604080850151600480548516918616919091178155606086015160098054861691871691821790556080870151600a8054871691881691909117905560a087015160088054871691881691909117905560c087015160058054871691881691909117905560e087015160068054909616961695909517909355805163313ce56760e01b8152905163313ce5679382810193928290030181865afa15801562000206573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022c9190620004cb565b60ff16600b55600a546040805163313ce56760e01b815290516001600160a01b039092169163313ce567916004808201926020929091908290030181865afa1580156200027d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002a39190620004cb565b60ff16600c556004805460408051630dfe168160e01b815290516000936001600160a01b0390931692630dfe1681928082019260209290918290030181865afa158015620002f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200031b9190620004f7565b6002549091506001600160a01b03908116908216036200034857600f805460ff1916600117905562000353565b600f805460ff191690555b600480546040805163748fc63b60e01b815290516001600160a01b039092169263748fc63b92828201926020929082900301816000875af11580156200039d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003c3919062000515565b601154620003d291906200052f565b601055506200055292505050565b80516001600160a01b0381168114620003f857600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060006101408085870312156200042b57600080fd5b6200043685620003e0565b9350602062000447818701620003e0565b935086605f8701126200045957600080fd5b60405161010081016001600160401b03811182821017156200047f576200047f620003fd565b6040529186019180888411156200049557600080fd5b604088015b84811015620004bc57620004ae81620003e0565b82529083019083016200049a565b50508093505050509250925092565b600060208284031215620004de57600080fd5b815160ff81168114620004f057600080fd5b9392505050565b6000602082840312156200050a57600080fd5b620004f082620003e0565b6000602082840312156200052857600080fd5b5051919050565b6000826200054d57634e487b7160e01b600052601260045260246000fd5b500490565b61293d80620005626000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806388b93d9a11610145578063bdacb303116100bd578063d882898f1161008c578063e8d5931d11610071578063e8d5931d14610551578063eb99aff814610564578063f8025c711461058457600080fd5b8063d882898f1461051e578063dc6663c71461053157600080fd5b8063bdacb303146104d9578063d2efde88146104ec578063d6c6c4ac146104f5578063d7bf3805146104fe57600080fd5b806395082d2511610114578063a4c3e73c116100f9578063a4c3e73c14610489578063b0e4556f146104a6578063b7fcc9d6146104c657600080fd5b806395082d25146104675780639c97ca1b1461047657600080fd5b806388b93d9a146104185780638980f11f1461042b5780638da5cb5b1461043e5780639238c0ac1461045e57600080fd5b80633a0319d7116101d8578063572a9302116101a757806379df39331161018c57806379df3933146103d85780638583f21c146103e157806387120c2f146103ea57600080fd5b8063572a9302146103bd57806379ba5097146103d057600080fd5b80633a0319d71461036c5780633a2b17a614610375578063536b265e1461039557806353a47bb71461039d57600080fd5b8063125ff6761161022f5780631627540c116102145780631627540c14610326578063200ea2221461033957806323fbd1c71461035957600080fd5b8063125ff676146102f6578063152129b21461030957600080fd5b806302825d111461026157806309761c7e146102765780630b9bc4c7146102915780630eb9a7d6146102d6575b600080fd5b61027461026f366004612488565b6105a4565b005b61027e6107ac565b6040519081526020015b60405180910390f35b6004546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610288565b6008546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b610274610304366004612488565b61091b565b600f546103169060ff1681565b6040519015158152602001610288565b6102746103343660046124c6565b610a71565b6003546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b610274610367366004612488565b610b8b565b61027e600d5481565b600a546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b61027e610d83565b6001546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b6102746103cb3660046124ea565b610ecd565b6102746110df565b61027e600b5481565b61027e60115481565b6103fd6103f8366004612523565b61122a565b60408051938452602084019290925290820152606001610288565b610274610426366004612488565b61186b565b61027461043936600461254f565b611a07565b6000546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b61027e60105481565b61027e670de0b6b3a764000081565b61027461048436600461254f565b611b22565b610491611c95565b60408051928352602083019190915201610288565b6002546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b6102746104d43660046124ea565b611ddd565b6102746104e73660046124c6565b611ed3565b61027e600e5481565b61027e600c5481565b6005546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b61027461052c36600461258a565b611fbd565b6007546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b61027461055f3660046125c5565b61226a565b6009546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b6006546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff163314806105e1575060075473ffffffffffffffffffffffffffffffffffffffff1633145b61064c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b000000000000000000000060448201526064015b60405180910390fd5b6003546005546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526024810184905291169063095ea7b3906044016020604051808303816000875af11580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb91906125fc565b506005546040517fe5d47fe00000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff9091169063e5d47fe090602401600060405180830381600087803b15801561075857600080fd5b505af115801561076c573d6000803e3d6000fd5b505050507fe558a54876ccdcca6af84fc4ec1c1d29df1db123d7d8b149bf4dad851ea46208816040516107a191815260200190565b60405180910390a150565b6000806000806000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108459190612631565b9450945050935093506000831215801561085e57508115155b801561088257508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b6108e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610643565b600b546108f690600a6127d2565b61090884670de0b6b3a76400006127de565b610912919061281b565b94505050505090565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610958575060075473ffffffffffffffffffffffffffffffffffffffff1633145b6109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600480546040517f1f4f5b4200000000000000000000000000000000000000000000000000000000815291820183905273ffffffffffffffffffffffffffffffffffffffff1690631f4f5b4290602401600060405180830381600087803b158015610a2857600080fd5b505af1158015610a3c573d6000803e3d6000fd5b505050507ff6b6b4f7a13f02512c1b3aa8dcc4a07d7775a6a4becbd439efcbd37c5408e67f816040516107a191815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610643565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020016107a1565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610bc8575060075473ffffffffffffffffffffffffffffffffffffffff1633145b610c2e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b6002546005546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526024810184905291169063095ea7b3906044016020604051808303816000875af1158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906125fc565b506005546040517f70c594750000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff909116906370c5947590602401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b505050507fda3eb31e87ed7d9058f251499bdb779e05dd9b0ea290c8ba6a50b6cd9fc3bb46816040516107a191815260200190565b6000806000806000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c9190612631565b94509450509350935060008312158015610e3557508115155b8015610e5957508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610643565b600c546108f690600a6127d2565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610f0a575060075473ffffffffffffffffffffffffffffffffffffffff1633145b610f70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b6009805473ffffffffffffffffffffffffffffffffffffffff8085167fffffffffffffffffffffffff00000000000000000000000000000000000000009283168117909355600a805491851691909216179055604080517f313ce567000000000000000000000000000000000000000000000000000000008152905163313ce567916004808201926020929091908290030181865afa158015611017573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103b9190612856565b60ff16600b55600a54604080517f313ce567000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163313ce567916004808201926020929091908290030181865afa1580156110b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d59190612856565b60ff16600c555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611186576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610643565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b600080548190819073ffffffffffffffffffffffffffffffffffffffff1633148061126c575060075473ffffffffffffffffffffffffffffffffffffffff1633145b6112d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b6000861180156112e25750600085115b15611349576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f43616e206f6e6c792073656c6c20696e206f6e6520646972656374696f6e00006044820152606401610643565b84156115b757849150600082116113bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f46585320736f6c64206d757374206265206e6f6e7a65726f00000000000000006044820152606401610643565b600e54821115611428576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f546f6f206d7563682046585320736f6c640000000000000000000000000000006044820152606401610643565b600354600480546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821692810192909252602482018590529091169063095ea7b3906044016020604051808303816000875af11580156114a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114cb91906125fc565b50600f5460ff161561158b5760045473ffffffffffffffffffffffffffffffffffffffff166381ca7998838661150357601054611505565b865b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303816000875af1158015611560573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115849190612873565b905061181b565b60045473ffffffffffffffffffffffffffffffffffffffff1663c9738a0d838661150357601054611505565b85925060008311611624576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4652415820736f6c64206d757374206265206e6f6e7a65726f000000000000006044820152606401610643565b600d54831115611690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f546f6f206d756368204652415820736f6c6400000000000000000000000000006044820152606401610643565b600254600480546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821692810192909252602482018690529091169063095ea7b3906044016020604051808303816000875af115801561170f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173391906125fc565b50600f5460ff161561176b5760045473ffffffffffffffffffffffffffffffffffffffff1663c9738a0d848661150357601054611505565b60045473ffffffffffffffffffffffffffffffffffffffff166381ca7998848661179757601054611799565b865b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303816000875af11580156117f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118189190612873565b90505b60408051828152602081018590529081018390524260608201527f8e423e515555b636ada542b287e7098e2f08ab4fe7c93834f12c78f9cbdc09d89060800160405180910390a193509350939050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806118a8575060075473ffffffffffffffffffffffffffffffffffffffff1633145b61190e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600480546040517f81fd0a46000000000000000000000000000000000000000000000000000000008152918201839052600091829173ffffffffffffffffffffffffffffffffffffffff16906381fd0a46906024016060604051808303816000875af1158015611982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a6919061288c565b6040805187815273ffffffffffffffffffffffffffffffffffffffff8416602082015290810182905291945092507fc9b310c79f0eaf708fffde12a4b9b4d76830d1962a5f6bb95e89c74b43820ff2915060600160405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611a44575060075473ffffffffffffffffffffffffffffffffffffffff1633145b611aaa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600054611acf90839073ffffffffffffffffffffffffffffffffffffffff1683612318565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f55350610fe57096d8c0ffa30beede987326bccfcb0b4415804164d0dd50ce8b1910160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611b5f575060075473ffffffffffffffffffffffffffffffffffffffff1633145b611bc5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841690811782556011839055604080517f748fc63b0000000000000000000000000000000000000000000000000000000081529051919263748fc63b92828201926020929082900301816000875af1158015611c60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c849190612873565b611c8e908261281b565b6010555050565b6002546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600091829173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015611d08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2c9190612873565b9150620f4240600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc39190612873565b611dcd90846127de565b611dd7919061281b565b90509091565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611e1a575060075473ffffffffffffffffffffffffffffffffffffffff1633145b611e80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b6008805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560068054929093169116179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611f10575060075473ffffffffffffffffffffffffffffffffffffffff1633145b611f76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611ffa575060075473ffffffffffffffffffffffffffffffffffffffff1633145b612060576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b8360ff166000036120af57821561207a5761207a83610b8b565b80156120aa576002546008546120aa9173ffffffffffffffffffffffffffffffffffffffff908116911683612318565b612219565b82156120be576120be836105a4565b81156121e9576003546006546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526024810185905291169063095ea7b3906044016020604051808303816000875af115801561213f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216391906125fc565b506006546040517f3c6b16ab0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff90911690633c6b16ab90602401600060405180830381600087803b1580156121d057600080fd5b505af11580156121e4573d6000803e3d6000fd5b505050505b8015612219576003546008546122199173ffffffffffffffffffffffffffffffffffffffff908116911683612318565b6040805160ff8616815260208101859052908101839052606081018290527fd03789b00b6410ba97de2c85996fe7d760e61c12b200e66131d597430a6ec1499060800160405180910390a150505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806122a7575060075473ffffffffffffffffffffffffffffffffffffffff1633145b61230d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600d91909155600e55565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916123af91906128cc565b6000604051808303816000865af19150503d80600081146123ec576040519150601f19603f3d011682016040523d82523d6000602084013e6123f1565b606091505b509150915081801561241b57508051158061241b57508080602001905181019061241b91906125fc565b612481576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610643565b5050505050565b60006020828403121561249a57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146124c357600080fd5b50565b6000602082840312156124d857600080fd5b81356124e3816124a1565b9392505050565b600080604083850312156124fd57600080fd5b8235612508816124a1565b91506020830135612518816124a1565b809150509250929050565b60008060006060848603121561253857600080fd5b505081359360208301359350604090920135919050565b6000806040838503121561256257600080fd5b823561256d816124a1565b946020939093013593505050565b60ff811681146124c357600080fd5b600080600080608085870312156125a057600080fd5b84356125ab8161257b565b966020860135965060408601359560600135945092505050565b600080604083850312156125d857600080fd5b50508035926020909101359150565b805180151581146125f757600080fd5b919050565b60006020828403121561260e57600080fd5b6124e3826125e7565b805169ffffffffffffffffffff811681146125f757600080fd5b600080600080600060a0868803121561264957600080fd5b61265286612617565b945060208601519350604086015192506060860151915061267560808701612617565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600181815b8085111561270957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156126ef576126ef612681565b808516156126fc57918102915b93841c93908002906126b5565b509250929050565b600082612720575060016127cc565b8161272d575060006127cc565b8160018114612743576002811461274d57612769565b60019150506127cc565b60ff84111561275e5761275e612681565b50506001821b6127cc565b5060208310610133831016604e8410600b841016171561278c575081810a6127cc565b61279683836126b0565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156127c8576127c8612681565b0290505b92915050565b60006124e38383612711565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561281657612816612681565b500290565b600082612851577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561286857600080fd5b81516124e38161257b565b60006020828403121561288557600080fd5b5051919050565b6000806000606084860312156128a157600080fd5b6128aa846125e7565b925060208401516128ba816124a1565b80925050604084015190509250925092565b6000825160005b818110156128ed57602081860181015185830152016128d3565b818111156128fc576000828501525b50919091019291505056fea2646970667358221220dfe2b697cf6db935b94152108c72ecd579949c687e4be701cf6bb4495654035964736f6c634300080d0033000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd20000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca000000000000000000000000853d955acef822db058eb8505911ed77f175b99e0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000008206412c107ef1adb70b9277974f5163760e128e000000000000000000000000b9e1e3a9feff48998e45fa90847ed4d467e8bcfd0000000000000000000000006ebc52c8c1089be9eb3945c4350b68b8e4c2233f000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000cf37b62109b537fa0cb9a90af4ca72f6fb85e241000000000000000000000000c6764e58b36e26b08fd1d2aed4538c02171fa872
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806388b93d9a11610145578063bdacb303116100bd578063d882898f1161008c578063e8d5931d11610071578063e8d5931d14610551578063eb99aff814610564578063f8025c711461058457600080fd5b8063d882898f1461051e578063dc6663c71461053157600080fd5b8063bdacb303146104d9578063d2efde88146104ec578063d6c6c4ac146104f5578063d7bf3805146104fe57600080fd5b806395082d2511610114578063a4c3e73c116100f9578063a4c3e73c14610489578063b0e4556f146104a6578063b7fcc9d6146104c657600080fd5b806395082d25146104675780639c97ca1b1461047657600080fd5b806388b93d9a146104185780638980f11f1461042b5780638da5cb5b1461043e5780639238c0ac1461045e57600080fd5b80633a0319d7116101d8578063572a9302116101a757806379df39331161018c57806379df3933146103d85780638583f21c146103e157806387120c2f146103ea57600080fd5b8063572a9302146103bd57806379ba5097146103d057600080fd5b80633a0319d71461036c5780633a2b17a614610375578063536b265e1461039557806353a47bb71461039d57600080fd5b8063125ff6761161022f5780631627540c116102145780631627540c14610326578063200ea2221461033957806323fbd1c71461035957600080fd5b8063125ff676146102f6578063152129b21461030957600080fd5b806302825d111461026157806309761c7e146102765780630b9bc4c7146102915780630eb9a7d6146102d6575b600080fd5b61027461026f366004612488565b6105a4565b005b61027e6107ac565b6040519081526020015b60405180910390f35b6004546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610288565b6008546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b610274610304366004612488565b61091b565b600f546103169060ff1681565b6040519015158152602001610288565b6102746103343660046124c6565b610a71565b6003546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b610274610367366004612488565b610b8b565b61027e600d5481565b600a546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b61027e610d83565b6001546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b6102746103cb3660046124ea565b610ecd565b6102746110df565b61027e600b5481565b61027e60115481565b6103fd6103f8366004612523565b61122a565b60408051938452602084019290925290820152606001610288565b610274610426366004612488565b61186b565b61027461043936600461254f565b611a07565b6000546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b61027e60105481565b61027e670de0b6b3a764000081565b61027461048436600461254f565b611b22565b610491611c95565b60408051928352602083019190915201610288565b6002546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b6102746104d43660046124ea565b611ddd565b6102746104e73660046124c6565b611ed3565b61027e600e5481565b61027e600c5481565b6005546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b61027461052c36600461258a565b611fbd565b6007546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b61027461055f3660046125c5565b61226a565b6009546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b6006546102b19073ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff163314806105e1575060075473ffffffffffffffffffffffffffffffffffffffff1633145b61064c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b000000000000000000000060448201526064015b60405180910390fd5b6003546005546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526024810184905291169063095ea7b3906044016020604051808303816000875af11580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb91906125fc565b506005546040517fe5d47fe00000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff9091169063e5d47fe090602401600060405180830381600087803b15801561075857600080fd5b505af115801561076c573d6000803e3d6000fd5b505050507fe558a54876ccdcca6af84fc4ec1c1d29df1db123d7d8b149bf4dad851ea46208816040516107a191815260200190565b60405180910390a150565b6000806000806000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108459190612631565b9450945050935093506000831215801561085e57508115155b801561088257508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b6108e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610643565b600b546108f690600a6127d2565b61090884670de0b6b3a76400006127de565b610912919061281b565b94505050505090565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610958575060075473ffffffffffffffffffffffffffffffffffffffff1633145b6109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600480546040517f1f4f5b4200000000000000000000000000000000000000000000000000000000815291820183905273ffffffffffffffffffffffffffffffffffffffff1690631f4f5b4290602401600060405180830381600087803b158015610a2857600080fd5b505af1158015610a3c573d6000803e3d6000fd5b505050507ff6b6b4f7a13f02512c1b3aa8dcc4a07d7775a6a4becbd439efcbd37c5408e67f816040516107a191815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610643565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020016107a1565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610bc8575060075473ffffffffffffffffffffffffffffffffffffffff1633145b610c2e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b6002546005546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526024810184905291169063095ea7b3906044016020604051808303816000875af1158015610ca9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccd91906125fc565b506005546040517f70c594750000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff909116906370c5947590602401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b505050507fda3eb31e87ed7d9058f251499bdb779e05dd9b0ea290c8ba6a50b6cd9fc3bb46816040516107a191815260200190565b6000806000806000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1c9190612631565b94509450509350935060008312158015610e3557508115155b8015610e5957508369ffffffffffffffffffff168169ffffffffffffffffffff1610155b610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420636861696e6c696e6b2070726963650000000000000000006044820152606401610643565b600c546108f690600a6127d2565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610f0a575060075473ffffffffffffffffffffffffffffffffffffffff1633145b610f70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b6009805473ffffffffffffffffffffffffffffffffffffffff8085167fffffffffffffffffffffffff00000000000000000000000000000000000000009283168117909355600a805491851691909216179055604080517f313ce567000000000000000000000000000000000000000000000000000000008152905163313ce567916004808201926020929091908290030181865afa158015611017573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103b9190612856565b60ff16600b55600a54604080517f313ce567000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163313ce567916004808201926020929091908290030181865afa1580156110b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d59190612856565b60ff16600c555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611186576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610643565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b600080548190819073ffffffffffffffffffffffffffffffffffffffff1633148061126c575060075473ffffffffffffffffffffffffffffffffffffffff1633145b6112d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b6000861180156112e25750600085115b15611349576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f43616e206f6e6c792073656c6c20696e206f6e6520646972656374696f6e00006044820152606401610643565b84156115b757849150600082116113bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f46585320736f6c64206d757374206265206e6f6e7a65726f00000000000000006044820152606401610643565b600e54821115611428576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f546f6f206d7563682046585320736f6c640000000000000000000000000000006044820152606401610643565b600354600480546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821692810192909252602482018590529091169063095ea7b3906044016020604051808303816000875af11580156114a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114cb91906125fc565b50600f5460ff161561158b5760045473ffffffffffffffffffffffffffffffffffffffff166381ca7998838661150357601054611505565b865b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303816000875af1158015611560573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115849190612873565b905061181b565b60045473ffffffffffffffffffffffffffffffffffffffff1663c9738a0d838661150357601054611505565b85925060008311611624576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4652415820736f6c64206d757374206265206e6f6e7a65726f000000000000006044820152606401610643565b600d54831115611690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f546f6f206d756368204652415820736f6c6400000000000000000000000000006044820152606401610643565b600254600480546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821692810192909252602482018690529091169063095ea7b3906044016020604051808303816000875af115801561170f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173391906125fc565b50600f5460ff161561176b5760045473ffffffffffffffffffffffffffffffffffffffff1663c9738a0d848661150357601054611505565b60045473ffffffffffffffffffffffffffffffffffffffff166381ca7998848661179757601054611799565b865b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303816000875af11580156117f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118189190612873565b90505b60408051828152602081018590529081018390524260608201527f8e423e515555b636ada542b287e7098e2f08ab4fe7c93834f12c78f9cbdc09d89060800160405180910390a193509350939050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806118a8575060075473ffffffffffffffffffffffffffffffffffffffff1633145b61190e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600480546040517f81fd0a46000000000000000000000000000000000000000000000000000000008152918201839052600091829173ffffffffffffffffffffffffffffffffffffffff16906381fd0a46906024016060604051808303816000875af1158015611982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a6919061288c565b6040805187815273ffffffffffffffffffffffffffffffffffffffff8416602082015290810182905291945092507fc9b310c79f0eaf708fffde12a4b9b4d76830d1962a5f6bb95e89c74b43820ff2915060600160405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611a44575060075473ffffffffffffffffffffffffffffffffffffffff1633145b611aaa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600054611acf90839073ffffffffffffffffffffffffffffffffffffffff1683612318565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f55350610fe57096d8c0ffa30beede987326bccfcb0b4415804164d0dd50ce8b1910160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611b5f575060075473ffffffffffffffffffffffffffffffffffffffff1633145b611bc5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841690811782556011839055604080517f748fc63b0000000000000000000000000000000000000000000000000000000081529051919263748fc63b92828201926020929082900301816000875af1158015611c60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c849190612873565b611c8e908261281b565b6010555050565b6002546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600091829173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015611d08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2c9190612873565b9150620f4240600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc39190612873565b611dcd90846127de565b611dd7919061281b565b90509091565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611e1a575060075473ffffffffffffffffffffffffffffffffffffffff1633145b611e80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b6008805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560068054929093169116179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611f10575060075473ffffffffffffffffffffffffffffffffffffffff1633145b611f76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331480611ffa575060075473ffffffffffffffffffffffffffffffffffffffff1633145b612060576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b8360ff166000036120af57821561207a5761207a83610b8b565b80156120aa576002546008546120aa9173ffffffffffffffffffffffffffffffffffffffff908116911683612318565b612219565b82156120be576120be836105a4565b81156121e9576003546006546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526024810185905291169063095ea7b3906044016020604051808303816000875af115801561213f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216391906125fc565b506006546040517f3c6b16ab0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff90911690633c6b16ab90602401600060405180830381600087803b1580156121d057600080fd5b505af11580156121e4573d6000803e3d6000fd5b505050505b8015612219576003546008546122199173ffffffffffffffffffffffffffffffffffffffff908116911683612318565b6040805160ff8616815260208101859052908101839052606081018290527fd03789b00b6410ba97de2c85996fe7d760e61c12b200e66131d597430a6ec1499060800160405180910390a150505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806122a7575060075473ffffffffffffffffffffffffffffffffffffffff1633145b61230d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610643565b600d91909155600e55565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916123af91906128cc565b6000604051808303816000865af19150503d80600081146123ec576040519150601f19603f3d011682016040523d82523d6000602084013e6123f1565b606091505b509150915081801561241b57508051158061241b57508080602001905181019061241b91906125fc565b612481576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610643565b5050505050565b60006020828403121561249a57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146124c357600080fd5b50565b6000602082840312156124d857600080fd5b81356124e3816124a1565b9392505050565b600080604083850312156124fd57600080fd5b8235612508816124a1565b91506020830135612518816124a1565b809150509250929050565b60008060006060848603121561253857600080fd5b505081359360208301359350604090920135919050565b6000806040838503121561256257600080fd5b823561256d816124a1565b946020939093013593505050565b60ff811681146124c357600080fd5b600080600080608085870312156125a057600080fd5b84356125ab8161257b565b966020860135965060408601359560600135945092505050565b600080604083850312156125d857600080fd5b50508035926020909101359150565b805180151581146125f757600080fd5b919050565b60006020828403121561260e57600080fd5b6124e3826125e7565b805169ffffffffffffffffffff811681146125f757600080fd5b600080600080600060a0868803121561264957600080fd5b61265286612617565b945060208601519350604086015192506060860151915061267560808701612617565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600181815b8085111561270957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156126ef576126ef612681565b808516156126fc57918102915b93841c93908002906126b5565b509250929050565b600082612720575060016127cc565b8161272d575060006127cc565b8160018114612743576002811461274d57612769565b60019150506127cc565b60ff84111561275e5761275e612681565b50506001821b6127cc565b5060208310610133831016604e8410600b841016171561278c575081810a6127cc565b61279683836126b0565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156127c8576127c8612681565b0290505b92915050565b60006124e38383612711565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561281657612816612681565b500290565b600082612851577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561286857600080fd5b81516124e38161257b565b60006020828403121561288557600080fd5b5051919050565b6000806000606084860312156128a157600080fd5b6128aa846125e7565b925060208401516128ba816124a1565b80925050604084015190509250925092565b6000825160005b818110156128ed57602081860181015185830152016128d3565b818111156128fc576000828501525b50919091019291505056fea2646970667358221220dfe2b697cf6db935b94152108c72ecd579949c687e4be701cf6bb4495654035964736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd20000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca000000000000000000000000853d955acef822db058eb8505911ed77f175b99e0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d00000000000000000000000008206412c107ef1adb70b9277974f5163760e128e000000000000000000000000b9e1e3a9feff48998e45fa90847ed4d467e8bcfd0000000000000000000000006ebc52c8c1089be9eb3945c4350b68b8e4c2233f000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27000000000000000000000000cf37b62109b537fa0cb9a90af4ca72f6fb85e241000000000000000000000000c6764e58b36e26b08fd1d2aed4538c02171fa872
-----Decoded View---------------
Arg [0] : _creator_address (address): 0x234D953a9404Bf9DbC3b526271d440cD2870bCd2
Arg [1] : _timelock_address (address): 0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA
Arg [2] : _address_pack (address[8]): 0x853d955aCEf822Db058eb8505911ED77F175b99e,0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0,0x8206412c107eF1aDb70B9277974f5163760E128E,0xB9E1E3A9feFf48998E45Fa90847ed4D467E8BcfD,0x6Ebc52C8C1089be9eB3945C4350B68B8E4C2233f,0xB1748C79709f4Ba2Dd82834B8c82D4a505003f27,0xcf37B62109b537fa0Cb9A90Af4CA72f6fb85E241,0xc6764e58b36e26b08Fd1d2AeD4538c02171fA872
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd2
Arg [1] : 0000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca
Arg [2] : 000000000000000000000000853d955acef822db058eb8505911ed77f175b99e
Arg [3] : 0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0
Arg [4] : 0000000000000000000000008206412c107ef1adb70b9277974f5163760e128e
Arg [5] : 000000000000000000000000b9e1e3a9feff48998e45fa90847ed4d467e8bcfd
Arg [6] : 0000000000000000000000006ebc52c8c1089be9eb3945c4350b68b8e4c2233f
Arg [7] : 000000000000000000000000b1748c79709f4ba2dd82834b8c82d4a505003f27
Arg [8] : 000000000000000000000000cf37b62109b537fa0cb9a90af4ca72f6fb85e241
Arg [9] : 000000000000000000000000c6764e58b36e26b08fd1d2aed4538c02171fa872
Deployed Bytecode Sourcemap
87260:10907:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95557:207;;;;;;:::i;:::-;;:::i;:::-;;90129:372;;;:::i;:::-;;;345:25:1;;;333:2;318:18;90129:372:0;;;;;;;;87356:34;;;;;;;;;;;;579:42:1;567:55;;;549:74;;537:2;522:18;87356:34:0;381:248:1;87529:27:0;;;;;;;;;93358:197;;;;;;:::i;:::-;;:::i;88096:26::-;;;;;;;;;;;;1030:14:1;;1023:22;1005:41;;993:2;978:18;88096:26:0;865:187:1;11765:141:0;;;;;;:::i;:::-;;:::i;87334:15::-;;;;;;;;;95283:215;;;;;;:::i;:::-;;:::i;87798:49::-;;;;;;87633:44;;;;;;;;;90543:369;;;:::i;11533:29::-;;;;;;;;;95828:403;;;;;;:::i;:::-;;:::i;11914:271::-;;;:::i;87684:42::-;;;;;;88220:38;;;;;;90986:2364;;;;;;:::i;:::-;;:::i;:::-;;;;2888:25:1;;;2944:2;2929:18;;2922:34;;;;2972:18;;;2965:34;2876:2;2861:18;90986:2364:0;2686:319:1;93563:305:0;;;;;;:::i;:::-;;:::i;97318:300::-;;;;;;:::i;:::-;;:::i;11506:20::-;;;;;;;;;88129:40;;;;;;88028:46;;88070:4;88028:46;;96239:315;;;;;;:::i;:::-;;:::i;89834:257::-;;;:::i;:::-;;;;3504:25:1;;;3560:2;3545:18;;3538:34;;;;3477:18;89834:257:0;3330:248:1;87310:17:0;;;;;;;;;96796:252;;;;;;:::i;:::-;;:::i;97056:133::-;;;;;;:::i;:::-;;:::i;87892:48::-;;;;;;87733:41;;;;;;87397:32;;;;;;;;;93915:1240;;;;;;:::i;:::-;;:::i;87491:31::-;;;;;;;;;96562:226;;;;;;:::i;:::-;;:::i;87581:45::-;;;;;;;;;87436:48;;;;;;;;;95557:207;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;;;;;;;;;95625:3:::1;::::0;95645:10:::1;::::0;95625:44:::1;::::0;;;;:3:::1;95645:10:::0;;::::1;95625:44;::::0;::::1;5692:74:1::0;5782:18;;;5775:34;;;95625:3:0;::::1;::::0;:11:::1;::::0;5665:18:1;;95625:44:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;95680:10:0::1;::::0;:37:::1;::::0;;;;::::1;::::0;::::1;345:25:1::0;;;95680:10:0::1;::::0;;::::1;::::0;:25:::1;::::0;318:18:1;;95680:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;95735:21;95745:10;95735:21;;;;345:25:1::0;;333:2;318:18;;199:177;95735:21:0::1;;;;;;;;95557:207:::0;:::o;90129:372::-;90177:7;90198:14;90214:9;90227:17;90246:22;90272:16;;;;;;;;;;;:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90197:109;;;;;;;;;90334:1;90325:5;:10;;:27;;;;-1:-1:-1;90339:13:0;;;90325:27;:57;;;;;90375:7;90356:26;;:15;:26;;;;90325:57;90317:93;;;;;;;7060:2:1;90317:93:0;;;7042:21:1;7099:2;7079:18;;;7072:30;7138:25;7118:18;;;7111:53;7181:18;;90317:93:0;6858:347:1;90317:93:0;90464:27;;90458:33;;:2;:33;:::i;:::-;90432:21;90440:5;90449:4;90432:21;:::i;:::-;90431:61;;;;:::i;:::-;90423:70;;;;;;90129:372;:::o;93358:197::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;93464:13:::1;::::0;;:42:::1;::::0;;;;;;::::1;345:25:1::0;;;93464:13:0::1;;::::0;:32:::1;::::0;318:18:1;;93464:42:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;93524:23;93538:8;93524:23;;;;345:25:1::0;;333:2;318:18;;199:177;11765:141:0;12245:5;;;;12231:10;:19;12223:79;;;;;;;9607:2:1;12223:79:0;;;9589:21:1;9646:2;9626:18;;;9619:30;9685:34;9665:18;;;9658:62;9756:17;9736:18;;;9729:45;9791:19;;12223:79:0;9405:411:1;12223:79:0;11837:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;11876:22:::1;::::0;549:74:1;;;11876:22:0::1;::::0;537:2:1;522:18;11876:22:0::1;381:248:1::0;95283:215:0;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;95353:4:::1;::::0;95374:10:::1;::::0;95353:46:::1;::::0;;;;:4:::1;95374:10:::0;;::::1;95353:46;::::0;::::1;5692:74:1::0;5782:18;;;5775:34;;;95353:4:0;::::1;::::0;:12:::1;::::0;5665:18:1;;95353:46:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;95410:10:0::1;::::0;:39:::1;::::0;;;;::::1;::::0;::::1;345:25:1::0;;;95410:10:0::1;::::0;;::::1;::::0;:26:::1;::::0;318:18:1;;95410:39:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;95467:23;95478:11;95467:23;;;;345:25:1::0;;333:2;318:18;;199:177;90543:369:0;90590:7;90611:14;90627:9;90640:17;90659:22;90685:15;;;;;;;;;;;:31;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90610:108;;;;;;;;;90746:1;90737:5;:10;;:27;;;;-1:-1:-1;90751:13:0;;;90737:27;:57;;;;;90787:7;90768:26;;:15;:26;;;;90737:57;90729:93;;;;;;;7060:2:1;90729:93:0;;;7042:21:1;7099:2;7079:18;;;7072:30;7138:25;7118:18;;;7111:53;7181:18;;90729:93:0;6858:347:1;90729:93:0;90876:26;;90870:32;;:2;:32;:::i;95828:403::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;95924:16:::1;:54:::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;95989:15:::1;:52:::0;;;;::::1;::::0;;;::::1;;::::0;;96130:27:::1;::::0;;;;;;;:25:::1;::::0;:27:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;95924:54;96130:27:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96100:57;;:27;:57:::0;96197:15:::1;::::0;:26:::1;::::0;;;;;;;:15:::1;::::0;;::::1;::::0;:24:::1;::::0;:26:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;:15;:26:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96168:55;;:26;:55:::0;-1:-1:-1;;95828:403:0:o;11914:271::-;11983:14;;;;11969:10;:28;11961:94;;;;;;;10275:2:1;11961:94:0;;;10257:21:1;10314:2;10294:18;;;10287:30;10353:34;10333:18;;;10326:62;10424:23;10404:18;;;10397:51;10465:19;;11961:94:0;10073:417:1;11961:94:0;12084:5;;;12091:14;12071:35;;;12084:5;;;;10730:34:1;;12091:14:0;;;;10795:2:1;10780:18;;10773:43;12071:35:0;;10642:18:1;12071:35:0;;;;;;;12125:14;;;;12117:22;;;;;;12125:14;;;12117:22;;;;12150:27;;;11914:271::o;90986:2364::-;91112:19;88379:5;;91112:19;;;;88379:5;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;91261:1:::1;91245:13;:17;91244:44;;;;;91286:1;91268:15;:19;91244:44;91242:47;91234:90;;;::::0;::::1;::::0;;11029:2:1;91234:90:0::1;::::0;::::1;11011:21:1::0;11068:2;11048:18;;;11041:30;11107:32;11087:18;;;11080:60;11157:18;;91234:90:0::1;10827:354:1::0;91234:90:0::1;91356:19:::0;;91352:1893:::1;;91500:15;91487:28;;91599:1;91586:10;:14;91578:51;;;::::0;::::1;::::0;;11388:2:1;91578:51:0::1;::::0;::::1;11370:21:1::0;11427:2;11407:18;;;11400:30;11466:26;11446:18;;;11439:54;11510:18;;91578:51:0::1;11186:348:1::0;91578:51:0::1;91705:19;;91691:10;:33;;91683:63;;;::::0;::::1;::::0;;11741:2:1;91683:63:0::1;::::0;::::1;11723:21:1::0;11780:2;11760:18;;;11753:30;11819:19;11799:18;;;11792:47;11856:18;;91683:63:0::1;11539:341:1::0;91683:63:0::1;91805:3;::::0;91825:13:::1;::::0;;91805:47:::1;::::0;;;;:3:::1;91825:13:::0;;::::1;91805:47:::0;;::::1;5692:74:1::0;;;;5782:18;;;5775:34;;;91805:3:0;;::::1;::::0;:11:::1;::::0;5665:18:1;;91805:47:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;91902:14:0::1;::::0;::::1;;91898:385;;;91956:13;::::0;::::1;;:34;91991:10:::0;92003:22;:65:::1;;92049:19;;92003:65;;;92028:18;92003:65;91956:113;::::0;;::::1;::::0;;;;;;::::1;::::0;::::1;3504:25:1::0;;;;3545:18;;;3538:34;3477:18;;91956:113:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91941:128;;91352:1893;;91898:385;92150:13;::::0;::::1;;:34;92185:10:::0;92197:22;:65:::1;;92243:19;;92197:65;;91352:1893;92443:13;92429:27;;92537:1;92523:11;:15;92515:53;;;::::0;::::1;::::0;;12276:2:1;92515:53:0::1;::::0;::::1;12258:21:1::0;12315:2;12295:18;;;12288:30;12354:27;12334:18;;;12327:55;12399:18;;92515:53:0::1;12074:349:1::0;92515:53:0::1;92645:20;;92630:11;:35;;92622:66;;;::::0;::::1;::::0;;12630:2:1;92622:66:0::1;::::0;::::1;12612:21:1::0;12669:2;12649:18;;;12642:30;12708:20;12688:18;;;12681:48;12746:18;;92622:66:0::1;12428:342:1::0;92622:66:0::1;92748:4;::::0;92769:13:::1;::::0;;92748:49:::1;::::0;;;;:4:::1;92769:13:::0;;::::1;92748:49:::0;;::::1;5692:74:1::0;;;;5782:18;;;5775:34;;;92748:4:0;;::::1;::::0;:12:::1;::::0;5665:18:1;;92748:49:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;92847:14:0::1;::::0;::::1;;92843:387;;;92901:13;::::0;::::1;;:34;92936:11:::0;92949:22;:65:::1;;92995:19;;92949:65;;92843:387;93096:13;::::0;::::1;;:34;93131:11:::0;93144:22;:65:::1;;93190:19;;93144:65;;;93169:18;93144:65;93096:114;::::0;;::::1;::::0;;;;;;::::1;::::0;::::1;3504:25:1::0;;;;3545:18;;;3538:34;3477:18;;93096:114:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93081:129;;92843:387;93273:69;::::0;;13006:25:1;;;13062:2;13047:18;;13040:34;;;13090:18;;;13083:34;;;93326:15:0::1;13148:2:1::0;13133:18;;13126:34;93273:69:0::1;::::0;12993:3:1;12978:19;93273:69:0::1;;;;;;;90986:2364:::0;;;;;;;:::o;93563:305::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;93731:13:::1;::::0;;:56:::1;::::0;;;;;;::::1;345:25:1::0;;;93689:17:0::1;::::0;;;93731:13:::1;;::::0;:46:::1;::::0;318:18:1;;93731:56:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93805:55;::::0;;13769:25:1;;;13842:42;13830:55;;13825:2;13810:18;;13803:83;13902:18;;;13895:34;;;93686:101:0;;-1:-1:-1;93686:101:0;-1:-1:-1;93805:55:0::1;::::0;-1:-1:-1;13757:2:1;13742:18;93805:55:0::1;;;;;;;93637:231;;93563:305:::0;:::o;97318:300::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;97534:5:::1;::::0;97492:61:::1;::::0;97520:12;;97534:5:::1;;97541:11:::0;97492:27:::1;:61::i;:::-;97569:41;::::0;;5722:42:1;5710:55;;5692:74;;5797:2;5782:18;;5775:34;;;97569:41:0::1;::::0;5665:18:1;97569:41:0::1;;;;;;;97318:300:::0;;:::o;96239:315::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;96386:13:::1;:42:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;96439:11:::1;:26:::0;;;96513:33:::1;::::0;;;;;;;96386:42;;96513:31:::1;::::0;:33;;::::1;::::0;::::1;::::0;;;;;;;-1:-1:-1;96386:42:0;96513:33:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96498:48;::::0;:12;:48:::1;:::i;:::-;96476:19;:70:::0;-1:-1:-1;;96239:315:0:o;89834:257::-;89953:4;;:29;;;;;89976:4;89953:29;;;549:74:1;89881:20:0;;;;89953:4;;;;;:14;;522:18:1;;89953:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89938:44;;90080:3;90046:4;;;;;;;;;;;:28;;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90031:45;;:12;:45;:::i;:::-;90030:53;;;;:::i;:::-;90013:70;;89834:257;;:::o;96796:252::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;96922:12:::1;:32:::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;96965:17:::1;:75:::0;;;;;::::1;::::0;::::1;;::::0;;96796:252::o;97056:133::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;97141:16:::1;:40:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;97056:133::o;93915:1240::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;94119:12:::1;:17;;94135:1;94119:17:::0;94115:932:::1;;94195:15:::0;;94191:42:::1;;94212:21;94221:11;94212:8;:21::i;:::-;94389:20:::0;;94385:100:::1;;94447:4;::::0;94454:12:::1;::::0;94411:74:::1;::::0;94447:4:::1;::::0;;::::1;::::0;94454:12:::1;94468:16:::0;94411:27:::1;:74::i;:::-;94115:932;;;94568:15:::0;;94564:41:::1;;94585:20;94593:11;94585:7;:20::i;:::-;94677:26:::0;;94673:209:::1;;94724:3;::::0;94744:17:::1;::::0;94724:63:::1;::::0;;;;:3:::1;94744:17:::0;;::::1;94724:63;::::0;::::1;5692:74:1::0;5782:18;;;5775:34;;;94724:3:0;::::1;::::0;:11:::1;::::0;5665:18:1;;94724:63:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;94806:17:0::1;::::0;:60:::1;::::0;;;;::::1;::::0;::::1;345:25:1::0;;;94806:17:0::1;::::0;;::::1;::::0;:36:::1;::::0;318:18:1;;94806:60:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;94673:209;94940:20:::0;;94936:99:::1;;94998:3;::::0;95004:12:::1;::::0;94962:73:::1;::::0;94998:3:::1;::::0;;::::1;::::0;95004:12:::1;95018:16:::0;94962:27:::1;:73::i;:::-;95064:83;::::0;;14197:4:1;14185:17;;14167:36;;14234:2;14219:18;;14212:34;;;14262:18;;;14255:34;;;14320:2;14305:18;;14298:34;;;95064:83:0::1;::::0;14154:3:1;14139:19;95064:83:0::1;;;;;;;93915:1240:::0;;;;:::o;96562:226::-;88379:5;;;;88365:10;:19;;:53;;-1:-1:-1;88402:16:0;;;;88388:10;:30;88365:53;88357:87;;;;;;;5370:2:1;88357:87:0;;;5352:21:1;5409:2;5389:18;;;5382:30;5448:23;5428:18;;;5421:51;5489:18;;88357:87:0;5168:345:1;88357:87:0;96683:20:::1;:44:::0;;;;96738:19:::1;:42:::0;96562:226::o;22864:361::-;23059:45;;;23048:10;5710:55:1;;;23059:45:0;;;5692:74:1;5782:18;;;;5775:34;;;23059:45:0;;;;;;;;;;5665:18:1;;;;23059:45:0;;;;;;;;;;;;;23048:57;;-1:-1:-1;;;;23048:10:0;;;;:57;;23059:45;23048:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23012:93;;;;23124:7;:57;;;;-1:-1:-1;23136:11:0;;:16;;:44;;;23167:4;23156:24;;;;;;;;;;;;:::i;:::-;23116:101;;;;;;;14976:2:1;23116:101:0;;;14958:21:1;15015:2;14995:18;;;14988:30;15054:33;15034:18;;;15027:61;15105:18;;23116:101:0;14774:355:1;23116:101:0;22934:291;;22864:361;;;:::o;14:180:1:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:1;;14:180;-1:-1:-1;14:180:1:o;1057:154::-;1143:42;1136:5;1132:54;1125:5;1122:65;1112:93;;1201:1;1198;1191:12;1112:93;1057:154;:::o;1216:247::-;1275:6;1328:2;1316:9;1307:7;1303:23;1299:32;1296:52;;;1344:1;1341;1334:12;1296:52;1383:9;1370:23;1402:31;1427:5;1402:31;:::i;:::-;1452:5;1216:247;-1:-1:-1;;;1216:247:1:o;1972:388::-;2040:6;2048;2101:2;2089:9;2080:7;2076:23;2072:32;2069:52;;;2117:1;2114;2107:12;2069:52;2156:9;2143:23;2175:31;2200:5;2175:31;:::i;:::-;2225:5;-1:-1:-1;2282:2:1;2267:18;;2254:32;2295:33;2254:32;2295:33;:::i;:::-;2347:7;2337:17;;;1972:388;;;;;:::o;2365:316::-;2442:6;2450;2458;2511:2;2499:9;2490:7;2486:23;2482:32;2479:52;;;2527:1;2524;2517:12;2479:52;-1:-1:-1;;2550:23:1;;;2620:2;2605:18;;2592:32;;-1:-1:-1;2671:2:1;2656:18;;;2643:32;;2365:316;-1:-1:-1;2365:316:1:o;3010:315::-;3078:6;3086;3139:2;3127:9;3118:7;3114:23;3110:32;3107:52;;;3155:1;3152;3145:12;3107:52;3194:9;3181:23;3213:31;3238:5;3213:31;:::i;:::-;3263:5;3315:2;3300:18;;;;3287:32;;-1:-1:-1;;;3010:315:1:o;4080:114::-;4164:4;4157:5;4153:16;4146:5;4143:27;4133:55;;4184:1;4181;4174:12;4199:448;4283:6;4291;4299;4307;4360:3;4348:9;4339:7;4335:23;4331:33;4328:53;;;4377:1;4374;4367:12;4328:53;4416:9;4403:23;4435:29;4458:5;4435:29;:::i;:::-;4483:5;4535:2;4520:18;;4507:32;;-1:-1:-1;4586:2:1;4571:18;;4558:32;;4637:2;4622:18;4609:32;;-1:-1:-1;4199:448:1;-1:-1:-1;;;4199:448:1:o;4652:248::-;4720:6;4728;4781:2;4769:9;4760:7;4756:23;4752:32;4749:52;;;4797:1;4794;4787:12;4749:52;-1:-1:-1;;4820:23:1;;;4890:2;4875:18;;;4862:32;;-1:-1:-1;4652:248:1:o;5820:164::-;5896:13;;5945;;5938:21;5928:32;;5918:60;;5974:1;5971;5964:12;5918:60;5820:164;;;:::o;5989:202::-;6056:6;6109:2;6097:9;6088:7;6084:23;6080:32;6077:52;;;6125:1;6122;6115:12;6077:52;6148:37;6175:9;6148:37;:::i;6196:179::-;6274:13;;6327:22;6316:34;;6306:45;;6296:73;;6365:1;6362;6355:12;6380:473;6483:6;6491;6499;6507;6515;6568:3;6556:9;6547:7;6543:23;6539:33;6536:53;;;6585:1;6582;6575:12;6536:53;6608:39;6637:9;6608:39;:::i;:::-;6598:49;;6687:2;6676:9;6672:18;6666:25;6656:35;;6731:2;6720:9;6716:18;6710:25;6700:35;;6775:2;6764:9;6760:18;6754:25;6744:35;;6798:49;6842:3;6831:9;6827:19;6798:49;:::i;:::-;6788:59;;6380:473;;;;;;;;:::o;7210:184::-;7262:77;7259:1;7252:88;7359:4;7356:1;7349:15;7383:4;7380:1;7373:15;7399:482;7488:1;7531:5;7488:1;7545:330;7566:7;7556:8;7553:21;7545:330;;;7685:4;7617:66;7613:77;7607:4;7604:87;7601:113;;;7694:18;;:::i;:::-;7744:7;7734:8;7730:22;7727:55;;;7764:16;;;;7727:55;7843:22;;;;7803:15;;;;7545:330;;;7549:3;7399:482;;;;;:::o;7886:866::-;7935:5;7965:8;7955:80;;-1:-1:-1;8006:1:1;8020:5;;7955:80;8054:4;8044:76;;-1:-1:-1;8091:1:1;8105:5;;8044:76;8136:4;8154:1;8149:59;;;;8222:1;8217:130;;;;8129:218;;8149:59;8179:1;8170:10;;8193:5;;;8217:130;8254:3;8244:8;8241:17;8238:43;;;8261:18;;:::i;:::-;-1:-1:-1;;8317:1:1;8303:16;;8332:5;;8129:218;;8431:2;8421:8;8418:16;8412:3;8406:4;8403:13;8399:36;8393:2;8383:8;8380:16;8375:2;8369:4;8366:12;8362:35;8359:77;8356:159;;;-1:-1:-1;8468:19:1;;;8500:5;;8356:159;8547:34;8572:8;8566:4;8547:34;:::i;:::-;8677:6;8609:66;8605:79;8596:7;8593:92;8590:118;;;8688:18;;:::i;:::-;8726:20;;-1:-1:-1;7886:866:1;;;;;:::o;8757:131::-;8817:5;8846:36;8873:8;8867:4;8846:36;:::i;8893:228::-;8933:7;9059:1;8991:66;8987:74;8984:1;8981:81;8976:1;8969:9;8962:17;8958:105;8955:131;;;9066:18;;:::i;:::-;-1:-1:-1;9106:9:1;;8893:228::o;9126:274::-;9166:1;9192;9182:189;;9227:77;9224:1;9217:88;9328:4;9325:1;9318:15;9356:4;9353:1;9346:15;9182:189;-1:-1:-1;9385:9:1;;9126:274::o;9821:247::-;9889:6;9942:2;9930:9;9921:7;9917:23;9913:32;9910:52;;;9958:1;9955;9948:12;9910:52;9990:9;9984:16;10009:29;10032:5;10009:29;:::i;11885:184::-;11955:6;12008:2;11996:9;11987:7;11983:23;11979:32;11976:52;;;12024:1;12021;12014:12;11976:52;-1:-1:-1;12047:16:1;;11885:184;-1:-1:-1;11885:184:1:o;13171:391::-;13256:6;13264;13272;13325:2;13313:9;13304:7;13300:23;13296:32;13293:52;;;13341:1;13338;13331:12;13293:52;13364:37;13391:9;13364:37;:::i;:::-;13354:47;;13444:2;13433:9;13429:18;13423:25;13457:31;13482:5;13457:31;:::i;:::-;13507:5;13497:15;;;13552:2;13541:9;13537:18;13531:25;13521:35;;13171:391;;;;;:::o;14343:426::-;14472:3;14510:6;14504:13;14535:1;14545:129;14559:6;14556:1;14553:13;14545:129;;;14657:4;14641:14;;;14637:25;;14631:32;14618:11;;;14611:53;14574:12;14545:129;;;14692:6;14689:1;14686:13;14683:48;;;14727:1;14718:6;14713:3;14709:16;14702:27;14683:48;-1:-1:-1;14747:16:1;;;;;14343:426;-1:-1:-1;;14343:426:1:o
Swarm Source
ipfs://dfe2b697cf6db935b94152108c72ecd579949c687e4be701cf6bb44956540359
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.