Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 92 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Migrate | 20475938 | 108 days ago | IN | 0 ETH | 0.00105033 | ||||
Remove Liquidity | 18419296 | 396 days ago | IN | 0 ETH | 0.00759919 | ||||
Remove Liquidity | 17705151 | 496 days ago | IN | 0 ETH | 0.00419174 | ||||
Remove Liquidity | 16820998 | 621 days ago | IN | 0 ETH | 0.01100187 | ||||
Remove Liquidity | 16129261 | 718 days ago | IN | 0 ETH | 0.00444345 | ||||
Remove Liquidity | 16129251 | 718 days ago | IN | 0 ETH | 0.00594893 | ||||
Remove Liquidity | 16128956 | 718 days ago | IN | 0 ETH | 0.00390664 | ||||
Remove Liquidity | 16115913 | 719 days ago | IN | 0 ETH | 0.00412682 | ||||
Deposit | 15965339 | 741 days ago | IN | 0 ETH | 0.00613122 | ||||
Deposit | 15650533 | 784 days ago | IN | 0 ETH | 0.00357008 | ||||
Send Dust | 15586613 | 793 days ago | IN | 0 ETH | 0.00032262 | ||||
Deposit | 15549982 | 799 days ago | IN | 0 ETH | 0.00313971 | ||||
Remove Liquidity | 15213831 | 852 days ago | IN | 0 ETH | 0.00535565 | ||||
U AD Price Reset | 15192836 | 855 days ago | IN | 0 ETH | 0.0197409 | ||||
Deposit | 14837983 | 914 days ago | IN | 0 ETH | 0.00843067 | ||||
Deposit | 14633572 | 946 days ago | IN | 0 ETH | 0.01959379 | ||||
Remove Liquidity | 14610787 | 950 days ago | IN | 0 ETH | 0.01849001 | ||||
Deposit | 14546954 | 960 days ago | IN | 0 ETH | 0.02574522 | ||||
Remove Liquidity | 14528446 | 963 days ago | IN | 0 ETH | 0.01958283 | ||||
Remove Liquidity | 14501815 | 967 days ago | IN | 0 ETH | 0.02174657 | ||||
Deposit | 14453602 | 974 days ago | IN | 0 ETH | 0.00991105 | ||||
Remove Liquidity | 14453545 | 974 days ago | IN | 0 ETH | 0.00827356 | ||||
Remove Liquidity | 14403892 | 982 days ago | IN | 0 ETH | 0.00899686 | ||||
Deposit | 14200345 | 1014 days ago | IN | 0 ETH | 0.0300842 | ||||
Deposit | 14200201 | 1014 days ago | IN | 0 ETH | 0.03155744 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
BondingV2
Compiler Version
v0.8.3+commit.8d00100c
Optimization Enabled:
Yes with 800 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "./interfaces/IERC1155Ubiquity.sol"; import "./interfaces/IMetaPool.sol"; import "./interfaces/IUbiquityFormulas.sol"; import "./UbiquityAlgorithmicDollar.sol"; import "./BondingFormulas.sol"; import "./BondingShareV2.sol"; import "./UbiquityAlgorithmicDollarManager.sol"; import "./interfaces/ISablier.sol"; import "./interfaces/IMasterChefV2.sol"; import "./interfaces/ITWAPOracle.sol"; import "./interfaces/IERC1155Ubiquity.sol"; import "./utils/CollectableDust.sol"; contract BondingV2 is CollectableDust, Pausable { using SafeERC20 for IERC20; bytes public data = ""; UbiquityAlgorithmicDollarManager public manager; uint256 public constant ONE = uint256(1 ether); // 3Crv has 18 decimals uint256 public bondingDiscountMultiplier = uint256(1000000 gwei); // 0.001 uint256 public blockCountInAWeek = 45361; uint256 public accLpRewardPerShare = 0; uint256 public lpRewards; uint256 public totalLpToMigrate; address public bondingFormulasAddress; address public migrator; // temporary address to handle migration address[] private _toMigrateOriginals; uint256[] private _toMigrateLpBalances; uint256[] private _toMigrateWeeks; // toMigrateId[address] > 0 when address is to migrate, or 0 in all other cases mapping(address => uint256) public toMigrateId; bool public migrating = false; event PriceReset( address _tokenWithdrawn, uint256 _amountWithdrawn, uint256 _amountTransfered ); event Deposit( address indexed _user, uint256 indexed _id, uint256 _lpAmount, uint256 _bondingShareAmount, uint256 _weeks, uint256 _endBlock ); event RemoveLiquidityFromBond( address indexed _user, uint256 indexed _id, uint256 _lpAmount, uint256 _lpAmountTransferred, uint256 _lprewards, uint256 _bondingShareAmount ); event AddLiquidityFromBond( address indexed _user, uint256 indexed _id, uint256 _lpAmount, uint256 _bondingShareAmount ); event BondingDiscountMultiplierUpdated(uint256 _bondingDiscountMultiplier); event BlockCountInAWeekUpdated(uint256 _blockCountInAWeek); event Migrated( address indexed _user, uint256 indexed _id, uint256 _lpsAmount, uint256 _sharesAmount, uint256 _weeks ); modifier onlyBondingManager() { require( manager.hasRole(manager.BONDING_MANAGER_ROLE(), msg.sender), "not manager" ); _; } modifier onlyPauser() { require( manager.hasRole(manager.PAUSER_ROLE(), msg.sender), "not pauser" ); _; } modifier onlyMigrator() { require(msg.sender == migrator, "not migrator"); _; } modifier whenMigrating() { require(migrating, "not in migration"); _; } constructor( address _manager, address _bondingFormulasAddress, address[] memory _originals, uint256[] memory _lpBalances, uint256[] memory _weeks ) CollectableDust() Pausable() { manager = UbiquityAlgorithmicDollarManager(_manager); bondingFormulasAddress = _bondingFormulasAddress; migrator = msg.sender; uint256 lgt = _originals.length; require(lgt > 0, "address array empty"); require(lgt == _lpBalances.length, "balances array not same length"); require(lgt == _weeks.length, "weeks array not same length"); _toMigrateOriginals = _originals; _toMigrateLpBalances = _lpBalances; _toMigrateWeeks = _weeks; for (uint256 i = 0; i < lgt; ++i) { toMigrateId[_originals[i]] = i + 1; totalLpToMigrate += _lpBalances[i]; } } // solhint-disable-next-line no-empty-blocks receive() external payable {} /// @dev addUserToMigrate add a user to migrate from V1. /// IMPORTANT execute that function BEFORE sending the corresponding LP token /// otherwise they will have extra LP rewards /// @param _original address of v1 user /// @param _lpBalance LP Balance of v1 user /// @param _weeks weeks lockup of v1 user /// @notice user will then be able to migrate. function addUserToMigrate( address _original, uint256 _lpBalance, uint256 _weeks ) external onlyMigrator { _toMigrateOriginals.push(_original); _toMigrateLpBalances.push(_lpBalance); totalLpToMigrate += _lpBalance; _toMigrateWeeks.push(_weeks); toMigrateId[_original] = _toMigrateOriginals.length; } function setMigrator(address _migrator) external onlyMigrator { migrator = _migrator; } function setMigrating(bool _migrating) external onlyMigrator { migrating = _migrating; } /// @dev uADPriceReset remove uAD unilateraly from the curve LP share sitting inside /// the bonding contract and send the uAD received to the treasury. /// This will have the immediate effect of pushing the uAD price HIGHER /// @param amount of LP token to be removed for uAD /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract function uADPriceReset(uint256 amount) external onlyBondingManager { IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress()); // remove one coin uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin( amount, 0, 0 ); ITWAPOracle(manager.twapOracleAddress()).update(); uint256 toTransfer = IERC20(manager.dollarTokenAddress()).balanceOf( address(this) ); IERC20(manager.dollarTokenAddress()).transfer( manager.treasuryAddress(), toTransfer ); emit PriceReset( manager.dollarTokenAddress(), coinWithdrawn, toTransfer ); } /// @dev crvPriceReset remove 3CRV unilateraly from the curve LP share sitting inside /// the bonding contract and send the 3CRV received to the treasury /// This will have the immediate effect of pushing the uAD price LOWER /// @param amount of LP token to be removed for 3CRV tokens /// @notice it will remove one coin only from the curve LP share sitting in the bonding contract function crvPriceReset(uint256 amount) external onlyBondingManager { IMetaPool metaPool = IMetaPool(manager.stableSwapMetaPoolAddress()); // remove one coin uint256 coinWithdrawn = metaPool.remove_liquidity_one_coin( amount, 1, 0 ); // update twap ITWAPOracle(manager.twapOracleAddress()).update(); uint256 toTransfer = IERC20(manager.curve3PoolTokenAddress()).balanceOf( address(this) ); IERC20(manager.curve3PoolTokenAddress()).transfer( manager.treasuryAddress(), toTransfer ); emit PriceReset( manager.curve3PoolTokenAddress(), coinWithdrawn, toTransfer ); } function setBondingFormulasAddress(address _bondingFormulasAddress) external onlyBondingManager { bondingFormulasAddress = _bondingFormulasAddress; } /// Collectable Dust function addProtocolToken(address _token) external override onlyBondingManager { _addProtocolToken(_token); } function removeProtocolToken(address _token) external override onlyBondingManager { _removeProtocolToken(_token); } function sendDust( address _to, address _token, uint256 _amount ) external override onlyBondingManager { _sendDust(_to, _token, _amount); } function setBondingDiscountMultiplier(uint256 _bondingDiscountMultiplier) external onlyBondingManager { bondingDiscountMultiplier = _bondingDiscountMultiplier; emit BondingDiscountMultiplierUpdated(_bondingDiscountMultiplier); } function setBlockCountInAWeek(uint256 _blockCountInAWeek) external onlyBondingManager { blockCountInAWeek = _blockCountInAWeek; emit BlockCountInAWeekUpdated(_blockCountInAWeek); } /// @dev deposit uAD-3CRV LP tokens for a duration to receive bonding shares /// @param _lpsAmount of LP token to send /// @param _weeks during lp token will be held /// @notice weeks act as a multiplier for the amount of bonding shares to be received function deposit(uint256 _lpsAmount, uint256 _weeks) external whenNotPaused returns (uint256 _id) { require( 1 <= _weeks && _weeks <= 208, "Bonding: duration must be between 1 and 208 weeks" ); ITWAPOracle(manager.twapOracleAddress()).update(); // update the accumulated lp rewards per shares _updateLpPerShare(); // transfer lp token to the bonding contract IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom( msg.sender, address(this), _lpsAmount ); // calculate the amount of share based on the amount of lp deposited and the duration uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress()) .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier); // calculate end locking period block number uint256 _endBlock = block.number + _weeks * blockCountInAWeek; _id = _mint(msg.sender, _lpsAmount, _sharesAmount, _endBlock); // set masterchef for uGOV rewards IMasterChefV2(manager.masterChefAddress()).deposit( msg.sender, _sharesAmount, _id ); emit Deposit( msg.sender, _id, _lpsAmount, _sharesAmount, _weeks, _endBlock ); } /// @dev Add an amount of uAD-3CRV LP tokens /// @param _amount of LP token to deposit /// @param _id bonding shares id /// @param _weeks during lp token will be held /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date function addLiquidity( uint256 _amount, uint256 _id, uint256 _weeks ) external whenNotPaused { ( uint256[2] memory bs, BondingShareV2.Bond memory bond ) = _checkForLiquidity(_id); // calculate pending LP rewards uint256 sharesToRemove = bs[0]; _updateLpPerShare(); uint256 pendingLpReward = lpRewardForShares( sharesToRemove, bond.lpRewardDebt ); // add an extra step to be able to decrease rewards if locking end is near pendingLpReward = BondingFormulas(this.bondingFormulasAddress()) .lpRewardsAddLiquidityNormalization(bond, bs, pendingLpReward); // add these LP Rewards to the deposited amount of LP token bond.lpAmount += pendingLpReward; lpRewards -= pendingLpReward; IERC20(manager.stableSwapMetaPoolAddress()).safeTransferFrom( msg.sender, address(this), _amount ); bond.lpAmount += _amount; // redeem all shares IMasterChefV2(manager.masterChefAddress()).withdraw( msg.sender, sharesToRemove, _id ); // calculate the amount of share based on the new amount of lp deposited and the duration uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress()) .durationMultiply(bond.lpAmount, _weeks, bondingDiscountMultiplier); // deposit new shares IMasterChefV2(manager.masterChefAddress()).deposit( msg.sender, _sharesAmount, _id ); // calculate end locking period block number // 1 week = 45361 blocks = 2371753*7/366 // n = (block + duration * 45361) bond.endBlock = block.number + _weeks * blockCountInAWeek; // should be done after masterchef withdraw _updateLpPerShare(); bond.lpRewardDebt = (IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo( _id )[0] * accLpRewardPerShare) / 1e12; BondingShareV2(manager.bondingShareAddress()).updateBond( _id, bond.lpAmount, bond.lpRewardDebt, bond.endBlock ); emit AddLiquidityFromBond( msg.sender, _id, bond.lpAmount, _sharesAmount ); } /// @dev Remove an amount of uAD-3CRV LP tokens /// @param _amount of LP token deposited when _id was created to be withdrawn /// @param _id bonding shares id /// @notice bonding shares are ERC1155 (aka NFT) because they have an expiration date function removeLiquidity(uint256 _amount, uint256 _id) external whenNotPaused { ( uint256[2] memory bs, BondingShareV2.Bond memory bond ) = _checkForLiquidity(_id); require(bond.lpAmount >= _amount, "Bonding: amount too big"); // we should decrease the UBQ rewards proportionally to the LP removed // sharesToRemove = (bonding shares * _amount ) / bond.lpAmount ; uint256 sharesToRemove = BondingFormulas(this.bondingFormulasAddress()) .sharesForLP(bond, bs, _amount); //get all its pending LP Rewards _updateLpPerShare(); uint256 pendingLpReward = lpRewardForShares(bs[0], bond.lpRewardDebt); // update bonding shares // bond.shares = bond.shares - sharesToRemove; // get masterchef for uGOV rewards To ensure correct computation // it needs to be done BEFORE updating the bonding share IMasterChefV2(manager.masterChefAddress()).withdraw( msg.sender, sharesToRemove, _id ); // redeem of the extra LP // bonding lp balance - BondingShareV2.totalLP IERC20 metapool = IERC20(manager.stableSwapMetaPoolAddress()); // add an extra step to be able to decrease rewards if locking end is near pendingLpReward = BondingFormulas(this.bondingFormulasAddress()) .lpRewardsRemoveLiquidityNormalization(bond, bs, pendingLpReward); uint256 correctedAmount = BondingFormulas(this.bondingFormulasAddress()) .correctedAmountToWithdraw( BondingShareV2(manager.bondingShareAddress()).totalLP(), metapool.balanceOf(address(this)) - lpRewards, _amount ); lpRewards -= pendingLpReward; bond.lpAmount -= _amount; // bond.lpRewardDebt = (bonding shares * accLpRewardPerShare) / 1e18; // user.amount.mul(pool.accSushiPerShare).div(1e12); // should be done after masterchef withdraw bond.lpRewardDebt = (IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo( _id )[0] * accLpRewardPerShare) / 1e12; BondingShareV2(manager.bondingShareAddress()).updateBond( _id, bond.lpAmount, bond.lpRewardDebt, bond.endBlock ); // lastly redeem lp tokens metapool.safeTransfer(msg.sender, correctedAmount + pendingLpReward); emit RemoveLiquidityFromBond( msg.sender, _id, _amount, correctedAmount, pendingLpReward, sharesToRemove ); } // View function to see pending lpRewards on frontend. function pendingLpRewards(uint256 _id) external view returns (uint256) { BondingShareV2 bonding = BondingShareV2(manager.bondingShareAddress()); BondingShareV2.Bond memory bond = bonding.getBond(_id); uint256[2] memory bs = IMasterChefV2(manager.masterChefAddress()) .getBondingShareInfo(_id); uint256 lpBalance = IERC20(manager.stableSwapMetaPoolAddress()) .balanceOf(address(this)); // the excess LP is the current balance minus the total deposited LP if (lpBalance >= (bonding.totalLP() + totalLpToMigrate)) { uint256 currentLpRewards = lpBalance - (bonding.totalLP() + totalLpToMigrate); uint256 curAccLpRewardPerShare = accLpRewardPerShare; // if new rewards we should calculate the new curAccLpRewardPerShare if (currentLpRewards > lpRewards) { uint256 newLpRewards = currentLpRewards - lpRewards; curAccLpRewardPerShare = accLpRewardPerShare + ((newLpRewards * 1e12) / IMasterChefV2(manager.masterChefAddress()) .totalShares()); } // we multiply the shares amount by the accumulated lpRewards per share // and remove the lp Reward Debt return (bs[0] * (curAccLpRewardPerShare)) / (1e12) - (bond.lpRewardDebt); } return 0; } function pause() public virtual onlyPauser { _pause(); } function unpause() public virtual onlyPauser { _unpause(); } /// @dev migrate let a user migrate from V1 /// @notice user will then be able to migrate function migrate() public whenMigrating returns (uint256 _id) { _id = toMigrateId[msg.sender]; require(_id > 0, "not v1 address"); _migrate( _toMigrateOriginals[_id - 1], _toMigrateLpBalances[_id - 1], _toMigrateWeeks[_id - 1] ); } /// @dev return the amount of Lp token rewards an amount of shares entitled /// @param amount of bonding shares /// @param lpRewardDebt lp rewards that has already been distributed function lpRewardForShares(uint256 amount, uint256 lpRewardDebt) public view returns (uint256 pendingLpReward) { if (accLpRewardPerShare > 0) { pendingLpReward = (amount * accLpRewardPerShare) / 1e12 - (lpRewardDebt); } } function currentShareValue() public view returns (uint256 priceShare) { uint256 totalShares = IMasterChefV2(manager.masterChefAddress()) .totalShares(); // priceShare = totalLP / totalShares priceShare = IUbiquityFormulas(manager.formulasAddress()).bondPrice( BondingShareV2(manager.bondingShareAddress()).totalLP(), totalShares, ONE ); } /// @dev migrate let a user migrate from V1 /// @notice user will then be able to migrate function _migrate( address user, uint256 _lpsAmount, uint256 _weeks ) internal returns (uint256 _id) { require(toMigrateId[user] > 0, "not v1 address"); require(_lpsAmount > 0, "LP amount is zero"); require( 1 <= _weeks && _weeks <= 208, "Duration must be between 1 and 208 weeks" ); // unregister address toMigrateId[user] = 0; // calculate the amount of share based on the amount of lp deposited and the duration uint256 _sharesAmount = IUbiquityFormulas(manager.formulasAddress()) .durationMultiply(_lpsAmount, _weeks, bondingDiscountMultiplier); // update the accumulated lp rewards per shares _updateLpPerShare(); // calculate end locking period block number uint256 endBlock = block.number + _weeks * blockCountInAWeek; _id = _mint(user, _lpsAmount, _sharesAmount, endBlock); // reduce the total LP to migrate after the minting // to keep the _updateLpPerShare calculation consistent totalLpToMigrate -= _lpsAmount; // set masterchef for uGOV rewards IMasterChefV2(manager.masterChefAddress()).deposit( user, _sharesAmount, _id ); emit Migrated(user, _id, _lpsAmount, _sharesAmount, _weeks); } /// @dev update the accumulated excess LP per share function _updateLpPerShare() internal { BondingShareV2 bond = BondingShareV2(manager.bondingShareAddress()); uint256 lpBalance = IERC20(manager.stableSwapMetaPoolAddress()) .balanceOf(address(this)); // the excess LP is the current balance // minus the total deposited LP + LP that needs to be migrated uint256 totalShares = IMasterChefV2(manager.masterChefAddress()) .totalShares(); if ( lpBalance >= (bond.totalLP() + totalLpToMigrate) && totalShares > 0 ) { uint256 currentLpRewards = lpBalance - (bond.totalLP() + totalLpToMigrate); // is there new LP rewards to be distributed ? if (currentLpRewards > lpRewards) { // we calculate the new accumulated LP rewards per share accLpRewardPerShare = accLpRewardPerShare + (((currentLpRewards - lpRewards) * 1e12) / totalShares); // update the bonding contract lpRewards lpRewards = currentLpRewards; } } } function _mint( address to, uint256 lpAmount, uint256 shares, uint256 endBlock ) internal returns (uint256) { uint256 _currentShareValue = currentShareValue(); require( _currentShareValue != 0, "Bonding: share value should not be null" ); // set the lp rewards debts so that this bonding share only get lp rewards from this day uint256 lpRewardDebt = (shares * accLpRewardPerShare) / 1e12; return BondingShareV2(manager.bondingShareAddress()).mint( to, lpAmount, lpRewardDebt, endBlock ); } function _checkForLiquidity(uint256 _id) internal returns (uint256[2] memory bs, BondingShareV2.Bond memory bond) { require( IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf( msg.sender, _id ) == 1, "Bonding: caller is not owner" ); BondingShareV2 bonding = BondingShareV2(manager.bondingShareAddress()); bond = bonding.getBond(_id); require( block.number > bond.endBlock, "Bonding: Redeem not allowed before bonding time" ); ITWAPOracle(manager.twapOracleAddress()).update(); bs = IMasterChefV2(manager.masterChefAddress()).getBondingShareInfo( _id ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.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 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' 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) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _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 require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.3; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; /// @title ERC1155 Ubiquiti preset interface /// @author Ubiquity Algorithmic Dollar interface IERC1155Ubiquity is IERC1155 { function mint( address to, uint256 id, uint256 amount, bytes memory data ) external; function mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) external; function burn( address account, uint256 id, uint256 value ) external; function burnBatch( address account, uint256[] memory ids, uint256[] memory values ) external; function pause() external; function unpause() external; function totalSupply() external view returns (uint256); function exists(uint256 id) external view returns (bool); function holderTokens() external view returns (uint256[] memory); }
// SPDX-License-Identifier: UNLICENSED // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! pragma solidity ^0.8.3; interface IMetaPool { event Transfer( address indexed sender, address indexed receiver, uint256 value ); event Approval( address indexed owner, address indexed spender, uint256 value ); event TokenExchange( address indexed buyer, int128 sold_id, uint256 tokens_sold, int128 bought_id, uint256 tokens_bought ); event TokenExchangeUnderlying( address indexed buyer, int128 sold_id, uint256 tokens_sold, int128 bought_id, uint256 tokens_bought ); event AddLiquidity( address indexed provider, uint256[2] token_amounts, uint256[2] fees, uint256 invariant, uint256 token_supply ); event RemoveLiquidity( address indexed provider, uint256[2] token_amounts, uint256[2] fees, uint256 token_supply ); event RemoveLiquidityOne( address indexed provider, uint256 token_amount, uint256 coin_amount, uint256 token_supply ); event RemoveLiquidityImbalance( address indexed provider, uint256[2] token_amounts, uint256[2] fees, uint256 invariant, uint256 token_supply ); event CommitNewAdmin(uint256 indexed deadline, address indexed admin); event NewAdmin(address indexed admin); event CommitNewFee( uint256 indexed deadline, uint256 fee, uint256 admin_fee ); event NewFee(uint256 fee, uint256 admin_fee); event RampA( uint256 old_A, uint256 new_A, uint256 initial_time, uint256 future_time ); event StopRampA(uint256 A, uint256 t); function initialize( string memory _name, string memory _symbol, address _coin, uint256 _decimals, uint256 _A, uint256 _fee, address _admin ) external; function decimals() external view returns (uint256); function transfer(address _to, uint256 _value) external returns (bool); function transferFrom( address _from, address _to, uint256 _value ) external returns (bool); function approve(address _spender, uint256 _value) external returns (bool); function get_previous_balances() external view returns (uint256[2] memory); function get_balances() external view returns (uint256[2] memory); function get_twap_balances( uint256[2] memory _first_balances, uint256[2] memory _last_balances, uint256 _time_elapsed ) external view returns (uint256[2] memory); function get_price_cumulative_last() external view returns (uint256[2] memory); function admin_fee() external view returns (uint256); function A() external view returns (uint256); function A_precise() external view returns (uint256); function get_virtual_price() external view returns (uint256); function calc_token_amount(uint256[2] memory _amounts, bool _is_deposit) external view returns (uint256); function calc_token_amount( uint256[2] memory _amounts, bool _is_deposit, bool _previous ) external view returns (uint256); function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount) external returns (uint256); function add_liquidity( uint256[2] memory _amounts, uint256 _min_mint_amount, address _receiver ) external returns (uint256); function get_dy( int128 i, int128 j, uint256 dx ) external view returns (uint256); function get_dy( int128 i, int128 j, uint256 dx, uint256[2] memory _balances ) external view returns (uint256); function get_dy_underlying( int128 i, int128 j, uint256 dx ) external view returns (uint256); function get_dy_underlying( int128 i, int128 j, uint256 dx, uint256[2] memory _balances ) external view returns (uint256); function exchange( int128 i, int128 j, uint256 dx, uint256 min_dy ) external returns (uint256); function exchange( int128 i, int128 j, uint256 dx, uint256 min_dy, address _receiver ) external returns (uint256); function exchange_underlying( int128 i, int128 j, uint256 dx, uint256 min_dy ) external returns (uint256); function exchange_underlying( int128 i, int128 j, uint256 dx, uint256 min_dy, address _receiver ) external returns (uint256); function remove_liquidity( uint256 _burn_amount, uint256[2] memory _min_amounts ) external returns (uint256[2] memory); function remove_liquidity( uint256 _burn_amount, uint256[2] memory _min_amounts, address _receiver ) external returns (uint256[2] memory); function remove_liquidity_imbalance( uint256[2] memory _amounts, uint256 _max_burn_amount ) external returns (uint256); function remove_liquidity_imbalance( uint256[2] memory _amounts, uint256 _max_burn_amount, address _receiver ) external returns (uint256); function calc_withdraw_one_coin(uint256 _burn_amount, int128 i) external view returns (uint256); function calc_withdraw_one_coin( uint256 _burn_amount, int128 i, bool _previous ) external view returns (uint256); function remove_liquidity_one_coin( uint256 _burn_amount, int128 i, uint256 _min_received ) external returns (uint256); function remove_liquidity_one_coin( uint256 _burn_amount, int128 i, uint256 _min_received, address _receiver ) external returns (uint256); function ramp_A(uint256 _future_A, uint256 _future_time) external; function stop_ramp_A() external; function admin_balances(uint256 i) external view returns (uint256); function withdraw_admin_fees() external; function admin() external view returns (address); function coins(uint256 arg0) external view returns (address); function balances(uint256 arg0) external view returns (uint256); function fee() external view returns (uint256); function block_timestamp_last() external view returns (uint256); function initial_A() external view returns (uint256); function future_A() external view returns (uint256); function initial_A_time() external view returns (uint256); function future_A_time() external view returns (uint256); function name() external view returns (string memory); function symbol() external view returns (string memory); function balanceOf(address arg0) external view returns (uint256); function allowance(address arg0, address arg1) external view returns (uint256); function totalSupply() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; interface IUbiquityFormulas { function durationMultiply( uint256 _uLP, uint256 _weeks, uint256 _multiplier ) external pure returns (uint256 _shares); function bonding( uint256 _shares, uint256 _currentShareValue, uint256 _targetPrice ) external pure returns (uint256 _uBOND); function redeemBonds( uint256 _uBOND, uint256 _currentShareValue, uint256 _targetPrice ) external pure returns (uint256 _uLP); function bondPrice( uint256 _totalULP, uint256 _totalUBOND, uint256 _targetPrice ) external pure returns (uint256 _priceUBOND); function ugovMultiply(uint256 _multiplier, uint256 _price) external pure returns (uint256 _newMultiplier); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; import "./interfaces/IIncentive.sol"; import "./ERC20Ubiquity.sol"; contract UbiquityAlgorithmicDollar is ERC20Ubiquity { /// @notice get associated incentive contract, 0 address if N/A mapping(address => address) public incentiveContract; event IncentiveContractUpdate( address indexed _incentivized, address indexed _incentiveContract ); constructor(address _manager) ERC20Ubiquity(_manager, "Ubiquity Algorithmic Dollar", "uAD") {} // solhint-disable-line no-empty-blocks /// @param account the account to incentivize /// @param incentive the associated incentive contract /// @notice only UAD manager can set Incentive contract function setIncentiveContract(address account, address incentive) external { require( ERC20Ubiquity.manager.hasRole( ERC20Ubiquity.manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender ), "Dollar: must have admin role" ); incentiveContract[account] = incentive; emit IncentiveContractUpdate(account, incentive); } function _checkAndApplyIncentives( address sender, address recipient, uint256 amount ) internal { // incentive on sender address senderIncentive = incentiveContract[sender]; if (senderIncentive != address(0)) { IIncentive(senderIncentive).incentivize( sender, recipient, msg.sender, amount ); } // incentive on recipient address recipientIncentive = incentiveContract[recipient]; if (recipientIncentive != address(0)) { IIncentive(recipientIncentive).incentivize( sender, recipient, msg.sender, amount ); } // incentive on operator address operatorIncentive = incentiveContract[msg.sender]; if ( msg.sender != sender && msg.sender != recipient && operatorIncentive != address(0) ) { IIncentive(operatorIncentive).incentivize( sender, recipient, msg.sender, amount ); } // all incentive, if active applies to every transfer address allIncentive = incentiveContract[address(0)]; if (allIncentive != address(0)) { IIncentive(allIncentive).incentivize( sender, recipient, msg.sender, amount ); } } function _transfer( address sender, address recipient, uint256 amount ) internal override { super._transfer(sender, recipient, amount); _checkAndApplyIncentives(sender, recipient, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; import "./BondingShareV2.sol"; import "./libs/ABDKMathQuad.sol"; import "./interfaces/IMasterChefV2.sol"; contract BondingFormulas { using ABDKMathQuad for uint256; using ABDKMathQuad for bytes16; uint256 public constant ONE = uint256(1 ether); // 18 decimals /// @dev formula UBQ Rights corresponding to a bonding shares LP amount /// @param _bond , bonding share /// @param _amount , amount of LP tokens /// @notice shares = (bond.shares * _amount ) / bond.lpAmount ; function sharesForLP( BondingShareV2.Bond memory _bond, uint256[2] memory _shareInfo, uint256 _amount ) public pure returns (uint256 _uLP) { bytes16 a = _shareInfo[0].fromUInt(); // shares amount bytes16 v = _amount.fromUInt(); bytes16 t = _bond.lpAmount.fromUInt(); _uLP = a.mul(v).div(t).toUInt(); } /// @dev formula may add a decreasing rewards if locking end is near when removing liquidity /// @param _bond , bonding share /// @param _amount , amount of LP tokens /// @notice rewards = _amount; // solhint-disable-block no-unused-vars /* solhint-disable no-unused-vars */ function lpRewardsRemoveLiquidityNormalization( BondingShareV2.Bond memory _bond, uint256[2] memory _shareInfo, uint256 _amount ) public pure returns (uint256) { return _amount; } /* solhint-enable no-unused-vars */ /// @dev formula may add a decreasing rewards if locking end is near when adding liquidity /// @param _bond , bonding share /// @param _amount , amount of LP tokens /// @notice rewards = _amount; // solhint-disable-block no-unused-vars /* solhint-disable no-unused-vars */ function lpRewardsAddLiquidityNormalization( BondingShareV2.Bond memory _bond, uint256[2] memory _shareInfo, uint256 _amount ) public pure returns (uint256) { return _amount; } /* solhint-enable no-unused-vars */ /// @dev formula to calculate the corrected amount to withdraw based on the proportion of /// lp deposited against actual LP token on thge bonding contract /// @param _totalLpDeposited , Total amount of LP deposited by users /// @param _bondingLpBalance , actual bonding contract LP tokens balance minus lp rewards /// @param _amount , amount of LP tokens /// @notice corrected_amount = amount * ( bondingLpBalance / totalLpDeposited) /// if there is more or the same amount of LP than deposited then do nothing function correctedAmountToWithdraw( uint256 _totalLpDeposited, uint256 _bondingLpBalance, uint256 _amount ) public pure returns (uint256) { if (_bondingLpBalance < _totalLpDeposited && _bondingLpBalance > 0) { // if there is less LP token inside the bonding contract that what have been deposited // we have to reduce proportionnaly the lp amount to withdraw return _amount .fromUInt() .mul(_bondingLpBalance.fromUInt()) .div(_totalLpDeposited.fromUInt()) .toUInt(); } return _amount; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol"; import "./UbiquityAlgorithmicDollarManager.sol"; import "./utils/SafeAddArray.sol"; contract BondingShareV2 is ERC1155, ERC1155Burnable, ERC1155Pausable { using SafeAddArray for uint256[]; struct Bond { // address of the minter address minter; // lp amount deposited by the user uint256 lpFirstDeposited; uint256 creationBlock; // lp that were already there when created uint256 lpRewardDebt; uint256 endBlock; // lp remaining for a user uint256 lpAmount; } UbiquityAlgorithmicDollarManager public manager; // Mapping from account to operator approvals mapping(address => uint256[]) private _holderBalances; mapping(uint256 => Bond) private _bonds; uint256 private _totalLP; uint256 private _totalSupply; // ----------- Modifiers ----------- modifier onlyMinter() { require( manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender), "Governance token: not minter" ); _; } modifier onlyBurner() { require( manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender), "Governance token: not burner" ); _; } modifier onlyPauser() { require( manager.hasRole(manager.PAUSER_ROLE(), msg.sender), "Governance token: not pauser" ); _; } /** * @dev constructor */ constructor(address _manager, string memory uri) ERC1155(uri) { manager = UbiquityAlgorithmicDollarManager(_manager); } /// @dev update bond LP amount , LP rewards debt and end block. /// @param _bondId bonding share id /// @param _lpAmount amount of LP token deposited /// @param _lpRewardDebt amount of excess LP token inside the bonding contract /// @param _endBlock end locking period block number function updateBond( uint256 _bondId, uint256 _lpAmount, uint256 _lpRewardDebt, uint256 _endBlock ) external onlyMinter whenNotPaused { Bond storage bond = _bonds[_bondId]; uint256 curLpAmount = bond.lpAmount; if (curLpAmount > _lpAmount) { // we are removing LP _totalLP -= curLpAmount - _lpAmount; } else { // we are adding LP _totalLP += _lpAmount - curLpAmount; } bond.lpAmount = _lpAmount; bond.lpRewardDebt = _lpRewardDebt; bond.endBlock = _endBlock; } // @dev Creates `amount` new tokens for `to`, of token type `id`. /// @param to owner address /// @param lpDeposited amount of LP token deposited /// @param lpRewardDebt amount of excess LP token inside the bonding contract /// @param endBlock block number when the locking period ends function mint( address to, uint256 lpDeposited, uint256 lpRewardDebt, uint256 endBlock ) public virtual onlyMinter whenNotPaused returns (uint256 id) { id = _totalSupply + 1; _mint(to, id, 1, bytes("")); _totalSupply += 1; _holderBalances[to].add(id); Bond storage _bond = _bonds[id]; _bond.minter = to; _bond.lpFirstDeposited = lpDeposited; _bond.lpAmount = lpDeposited; _bond.lpRewardDebt = lpRewardDebt; _bond.creationBlock = block.number; _bond.endBlock = endBlock; _totalLP += lpDeposited; } /** * @dev Pauses all token transfers. * * See {ERC1155Pausable} and {Pausable-_pause}. * */ function pause() public virtual onlyPauser { _pause(); } /** * @dev Unpauses all token transfers. * * See {ERC1155Pausable} and {Pausable-_unpause}. * */ function unpause() public virtual onlyPauser { _unpause(); } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public override whenNotPaused { super.safeTransferFrom(from, to, id, amount, data); _holderBalances[to].add(id); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override whenNotPaused { super.safeBatchTransferFrom(from, to, ids, amounts, data); _holderBalances[to].add(ids); } /** * @dev Total amount of tokens . */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev Total amount of LP tokens deposited. */ function totalLP() public view virtual returns (uint256) { return _totalLP; } /** * @dev return bond details. */ function getBond(uint256 id) public view returns (Bond memory) { return _bonds[id]; } /** * @dev array of token Id held by the msg.sender. */ function holderTokens(address holder) public view returns (uint256[] memory) { return _holderBalances[holder]; } function _burn( address account, uint256 id, uint256 amount ) internal virtual override whenNotPaused { require(amount == 1, "amount <> 1"); super._burn(account, id, 1); Bond storage _bond = _bonds[id]; require(_bond.lpAmount == 0, "LP <> 0"); _totalSupply -= 1; } function _burnBatch( address account, uint256[] memory ids, uint256[] memory amounts ) internal virtual override whenNotPaused { super._burnBatch(account, ids, amounts); for (uint256 i = 0; i < ids.length; ++i) { _totalSupply -= amounts[i]; } } function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override(ERC1155, ERC1155Pausable) { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./interfaces/IUbiquityAlgorithmicDollar.sol"; import "./interfaces/ICurveFactory.sol"; import "./interfaces/IMetaPool.sol"; import "./TWAPOracle.sol"; /// @title A central config for the uAD system. Also acts as a central /// access control manager. /// @notice For storing constants. For storing variables and allowing them to /// be changed by the admin (governance) /// @dev This should be used as a central access control manager which other /// contracts use to check permissions contract UbiquityAlgorithmicDollarManager is AccessControl { using SafeERC20 for IERC20; bytes32 public constant UBQ_MINTER_ROLE = keccak256("UBQ_MINTER_ROLE"); bytes32 public constant UBQ_BURNER_ROLE = keccak256("UBQ_BURNER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant COUPON_MANAGER_ROLE = keccak256("COUPON_MANAGER"); bytes32 public constant BONDING_MANAGER_ROLE = keccak256("BONDING_MANAGER"); bytes32 public constant INCENTIVE_MANAGER_ROLE = keccak256("INCENTIVE_MANAGER"); bytes32 public constant UBQ_TOKEN_MANAGER_ROLE = keccak256("UBQ_TOKEN_MANAGER_ROLE"); address public twapOracleAddress; address public debtCouponAddress; address public dollarTokenAddress; // uAD address public couponCalculatorAddress; address public dollarMintingCalculatorAddress; address public bondingShareAddress; address public bondingContractAddress; address public stableSwapMetaPoolAddress; address public curve3PoolTokenAddress; // 3CRV address public treasuryAddress; address public governanceTokenAddress; // uGOV address public sushiSwapPoolAddress; // sushi pool uAD-uGOV address public masterChefAddress; address public formulasAddress; address public autoRedeemTokenAddress; // uAR address public uarCalculatorAddress; // uAR calculator //key = address of couponmanager, value = excessdollardistributor mapping(address => address) private _excessDollarDistributors; modifier onlyAdmin() { require( hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "uADMGR: Caller is not admin" ); _; } constructor(address _admin) { _setupRole(DEFAULT_ADMIN_ROLE, _admin); _setupRole(UBQ_MINTER_ROLE, _admin); _setupRole(PAUSER_ROLE, _admin); _setupRole(COUPON_MANAGER_ROLE, _admin); _setupRole(BONDING_MANAGER_ROLE, _admin); _setupRole(INCENTIVE_MANAGER_ROLE, _admin); _setupRole(UBQ_TOKEN_MANAGER_ROLE, address(this)); } // TODO Add a generic setter for extra addresses that needs to be linked function setTwapOracleAddress(address _twapOracleAddress) external onlyAdmin { twapOracleAddress = _twapOracleAddress; // to be removed TWAPOracle oracle = TWAPOracle(twapOracleAddress); oracle.update(); } function setuARTokenAddress(address _uarTokenAddress) external onlyAdmin { autoRedeemTokenAddress = _uarTokenAddress; } function setDebtCouponAddress(address _debtCouponAddress) external onlyAdmin { debtCouponAddress = _debtCouponAddress; } function setIncentiveToUAD(address _account, address _incentiveAddress) external onlyAdmin { IUbiquityAlgorithmicDollar(dollarTokenAddress).setIncentiveContract( _account, _incentiveAddress ); } function setDollarTokenAddress(address _dollarTokenAddress) external onlyAdmin { dollarTokenAddress = _dollarTokenAddress; } function setGovernanceTokenAddress(address _governanceTokenAddress) external onlyAdmin { governanceTokenAddress = _governanceTokenAddress; } function setSushiSwapPoolAddress(address _sushiSwapPoolAddress) external onlyAdmin { sushiSwapPoolAddress = _sushiSwapPoolAddress; } function setUARCalculatorAddress(address _uarCalculatorAddress) external onlyAdmin { uarCalculatorAddress = _uarCalculatorAddress; } function setCouponCalculatorAddress(address _couponCalculatorAddress) external onlyAdmin { couponCalculatorAddress = _couponCalculatorAddress; } function setDollarMintingCalculatorAddress( address _dollarMintingCalculatorAddress ) external onlyAdmin { dollarMintingCalculatorAddress = _dollarMintingCalculatorAddress; } function setExcessDollarsDistributor( address debtCouponManagerAddress, address excessCouponDistributor ) external onlyAdmin { _excessDollarDistributors[ debtCouponManagerAddress ] = excessCouponDistributor; } function setMasterChefAddress(address _masterChefAddress) external onlyAdmin { masterChefAddress = _masterChefAddress; } function setFormulasAddress(address _formulasAddress) external onlyAdmin { formulasAddress = _formulasAddress; } function setBondingShareAddress(address _bondingShareAddress) external onlyAdmin { bondingShareAddress = _bondingShareAddress; } function setStableSwapMetaPoolAddress(address _stableSwapMetaPoolAddress) external onlyAdmin { stableSwapMetaPoolAddress = _stableSwapMetaPoolAddress; } /** @notice set the bonding bontract smart contract address @dev bonding contract participants deposit curve LP token for a certain duration to earn uGOV and more curve LP token @param _bondingContractAddress bonding contract address */ function setBondingContractAddress(address _bondingContractAddress) external onlyAdmin { bondingContractAddress = _bondingContractAddress; } /** @notice set the treasury address @dev the treasury fund is used to maintain the protocol @param _treasuryAddress treasury fund address */ function setTreasuryAddress(address _treasuryAddress) external onlyAdmin { treasuryAddress = _treasuryAddress; } /** @notice deploy a new Curve metapools for uAD Token uAD/3Pool @dev From the curve documentation for uncollateralized algorithmic stablecoins amplification should be 5-10 @param _curveFactory MetaPool factory address @param _crvBasePool Address of the base pool to use within the new metapool. @param _crv3PoolTokenAddress curve 3Pool token Address @param _amplificationCoefficient amplification coefficient. The smaller it is the closer to a constant product we are. @param _fee Trade fee, given as an integer with 1e10 precision. */ function deployStableSwapPool( address _curveFactory, address _crvBasePool, address _crv3PoolTokenAddress, uint256 _amplificationCoefficient, uint256 _fee ) external onlyAdmin { // Create new StableSwap meta pool (uAD <-> 3Crv) address metaPool = ICurveFactory(_curveFactory).deploy_metapool( _crvBasePool, ERC20(dollarTokenAddress).name(), ERC20(dollarTokenAddress).symbol(), dollarTokenAddress, _amplificationCoefficient, _fee ); stableSwapMetaPoolAddress = metaPool; // Approve the newly-deployed meta pool to transfer this contract's funds uint256 crv3PoolTokenAmount = IERC20(_crv3PoolTokenAddress).balanceOf( address(this) ); uint256 uADTokenAmount = IERC20(dollarTokenAddress).balanceOf( address(this) ); // safe approve revert if approve from non-zero to non-zero allowance IERC20(_crv3PoolTokenAddress).safeApprove(metaPool, 0); IERC20(_crv3PoolTokenAddress).safeApprove( metaPool, crv3PoolTokenAmount ); IERC20(dollarTokenAddress).safeApprove(metaPool, 0); IERC20(dollarTokenAddress).safeApprove(metaPool, uADTokenAmount); // coin at index 0 is uAD and index 1 is 3CRV require( IMetaPool(metaPool).coins(0) == dollarTokenAddress && IMetaPool(metaPool).coins(1) == _crv3PoolTokenAddress, "uADMGR: COIN_ORDER_MISMATCH" ); // Add the initial liquidity to the StableSwap meta pool uint256[2] memory amounts = [ IERC20(dollarTokenAddress).balanceOf(address(this)), IERC20(_crv3PoolTokenAddress).balanceOf(address(this)) ]; // set curve 3Pool address curve3PoolTokenAddress = _crv3PoolTokenAddress; IMetaPool(metaPool).add_liquidity(amounts, 0, msg.sender); } function getExcessDollarsDistributor(address _debtCouponManagerAddress) external view returns (address) { return _excessDollarDistributors[_debtCouponManagerAddress]; } }
// SPDX-License-Identifier: MIT // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! pragma solidity ^0.8.3; interface ISablier { event CreateCompoundingStream( uint256 indexed streamId, uint256 exchangeRate, uint256 senderSharePercentage, uint256 recipientSharePercentage ); event PayInterest( uint256 indexed streamId, uint256 senderInterest, uint256 recipientInterest, uint256 sablierInterest ); event TakeEarnings(address indexed tokenAddress, uint256 indexed amount); event UpdateFee(uint256 indexed fee); event Paused(address account); event Unpaused(address account); event PauserAdded(address indexed account); event PauserRemoved(address indexed account); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); event CreateStream( uint256 indexed streamId, address indexed sender, address indexed recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime ); event WithdrawFromStream( uint256 indexed streamId, address indexed recipient, uint256 amount ); event CancelStream( uint256 indexed streamId, address indexed sender, address indexed recipient, uint256 senderBalance, uint256 recipientBalance ); function unpause() external; function cancelStream(uint256 streamId) external returns (bool); function withdrawFromStream(uint256 streamId, uint256 amount) external returns (bool); function initialize() external; function createCompoundingStream( address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime, uint256 senderSharePercentage, uint256 recipientSharePercentage ) external returns (uint256); function addPauser(address account) external; function pause() external; function interestOf(uint256 streamId, uint256 amount) external returns ( uint256 senderInterest, uint256 recipientInterest, uint256 sablierInterest ); function updateFee(uint256 feePercentage) external; function takeEarnings(address tokenAddress, uint256 amount) external; function initialize(address sender) external; function createStream( address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime ) external returns (uint256); function transferOwnership(address newOwner) external; function getEarnings(address tokenAddress) external view returns (uint256); function nextStreamId() external view returns (uint256); function getCompoundingStream(uint256 streamId) external view returns ( address sender, address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime, uint256 remainingBalance, uint256 ratePerSecond, uint256 exchangeRateInitial, uint256 senderSharePercentage, uint256 recipientSharePercentage ); function balanceOf(uint256 streamId, address who) external view returns (uint256 balance); function isPauser(address account) external view returns (bool); function paused() external view returns (bool); function getStream(uint256 streamId) external view returns ( address sender, address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime, uint256 remainingBalance, uint256 ratePerSecond ); function owner() external view returns (address); function isOwner() external view returns (bool); function isCompoundingStream(uint256 streamId) external view returns (bool); function deltaOf(uint256 streamId) external view returns (uint256 delta); function cTokenManager() external view returns (address); function fee() external view returns (uint256 mantissa); }
// SPDX-License-Identifier: UNLICENSED // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! pragma solidity ^0.8.3; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../MasterChefV2.sol"; interface IMasterChefV2 { struct BondingShareInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. } struct PoolInfo { uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs. uint256 accuGOVPerShare; // Accumulated SUSHI per share, times 1e12. See below. } event Deposit(address indexed user, uint256 amount, uint256 bondingShareID); event Withdraw( address indexed user, uint256 amount, uint256 bondingShareID ); function deposit( address sender, uint256 amount, uint256 bondingShareID ) external; // Withdraw LP tokens from MasterChef. function withdraw( address sender, uint256 amount, uint256 bondingShareID ) external; // Info about a bondinh share function getBondingShareInfo(uint256 _id) external view returns (uint256[2] memory); // Total amount of shares function totalShares() external view returns (uint256); // View function to see pending SUSHIs on frontend. function pendingUGOV(address _user) external view returns (uint256); } // THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; interface ITWAPOracle { function update() external; function consult(address token) external view returns (uint256 amountOut); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../interfaces/utils/ICollectableDust.sol"; abstract contract CollectableDust is ICollectableDust { using SafeERC20 for IERC20; using EnumerableSet for EnumerableSet.AddressSet; address public constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; EnumerableSet.AddressSet internal _protocolTokens; // solhint-disable-next-line no-empty-blocks constructor() {} function _addProtocolToken(address _token) internal { require( !_protocolTokens.contains(_token), "collectable-dust::token-is-part-of-the-protocol" ); _protocolTokens.add(_token); emit ProtocolTokenAdded(_token); } function _removeProtocolToken(address _token) internal { require( _protocolTokens.contains(_token), "collectable-dust::token-not-part-of-the-protocol" ); _protocolTokens.remove(_token); emit ProtocolTokenRemoved(_token); } function _sendDust( address _to, address _token, uint256 _amount ) internal { require( _to != address(0), "collectable-dust::cant-send-dust-to-zero-address" ); require( !_protocolTokens.contains(_token), "collectable-dust::token-is-part-of-the-protocol" ); if (_token == ETH_ADDRESS) { payable(_to).transfer(_amount); } else { IERC20(_token).safeTransfer(_to, _amount); } emit DustSent(_to, _token, _amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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; 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"); (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"); (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"); (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"); (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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /* * @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 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) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; /// @title incentive contract interface /// @notice Called by uAD token contract when transferring with an incentivized address /// @dev should be appointed as a Minter or Burner as needed interface IIncentive { /// @notice apply incentives on transfer /// @param sender the sender address of uAD /// @param receiver the receiver address of uAD /// @param operator the operator (msg.sender) of the transfer /// @param amount the amount of uAD transferred function incentivize( address sender, address receiver, address operator, uint256 amount ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; import "./UbiquityAlgorithmicDollarManager.sol"; import "./interfaces/IERC20Ubiquity.sol"; /// @title ERC20 Ubiquity preset /// @author Ubiquity Algorithmic Dollar /// @notice ERC20 with : /// - ERC20 minter, burner and pauser /// - draft-ERC20 permit /// - Ubiquity Manager access control contract ERC20Ubiquity is IERC20Ubiquity, ERC20, ERC20Burnable, ERC20Pausable { UbiquityAlgorithmicDollarManager public manager; // solhint-disable-next-line var-name-mixedcase bytes32 public DOMAIN_SEPARATOR; // keccak256("Permit(address owner,address spender, // uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; mapping(address => uint256) public nonces; string private _tokenName; string private _symbol; // ----------- Modifiers ----------- modifier onlyMinter() { require( manager.hasRole(manager.UBQ_MINTER_ROLE(), msg.sender), "Governance token: not minter" ); _; } modifier onlyBurner() { require( manager.hasRole(manager.UBQ_BURNER_ROLE(), msg.sender), "Governance token: not burner" ); _; } modifier onlyPauser() { require( manager.hasRole(manager.PAUSER_ROLE(), msg.sender), "Governance token: not pauser" ); _; } modifier onlyAdmin() { require( manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender), "ERC20: deployer must be manager admin" ); _; } constructor( address _manager, string memory name_, string memory symbol_ ) ERC20(name_, symbol_) { _tokenName = name_; _symbol = symbol_; manager = UbiquityAlgorithmicDollarManager(_manager); // sender must be UbiquityAlgorithmicDollarManager roleAdmin // because he will get the admin, minter and pauser role on uAD and we want to // manage all permissions through the manager require( manager.hasRole(manager.DEFAULT_ADMIN_ROLE(), msg.sender), "ERC20: deployer must be manager admin" ); uint256 chainId; // solhint-disable-next-line no-inline-assembly assembly { chainId := chainid() } DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256( // solhint-disable-next-line max-line-length "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ), keccak256(bytes(name())), keccak256(bytes("1")), chainId, address(this) ) ); } /// @notice setSymbol update token symbol /// @param newSymbol new token symbol function setSymbol(string memory newSymbol) external onlyAdmin { _symbol = newSymbol; } /// @notice setName update token name /// @param newName new token name function setName(string memory newName) external onlyAdmin { _tokenName = newName; } /// @notice permit spending of uAD. owner has signed a message allowing /// spender to transfer up to amount uAD /// @param owner the uAD holder /// @param spender the approved operator /// @param value the amount approved /// @param deadline the deadline after which the approval is no longer valid function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external override { // solhint-disable-next-line not-rely-on-time require(deadline >= block.timestamp, "Dollar: EXPIRED"); bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256( abi.encode( PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline ) ) ) ); address recoveredAddress = ecrecover(digest, v, r, s); require( recoveredAddress != address(0) && recoveredAddress == owner, "Dollar: INVALID_SIGNATURE" ); _approve(owner, spender, value); } /// @notice burn UAD tokens from caller /// @param amount the amount to burn function burn(uint256 amount) public override(ERC20Burnable, IERC20Ubiquity) whenNotPaused { super.burn(amount); emit Burning(msg.sender, amount); } /// @notice burn uAD tokens from specified account /// @param account the account to burn from /// @param amount the amount to burn function burnFrom(address account, uint256 amount) public override(ERC20Burnable, IERC20Ubiquity) onlyBurner whenNotPaused // to suppress ? if BURNER_ROLE should do it even paused ? { _burn(account, amount); emit Burning(account, amount); } // @dev Creates `amount` new tokens for `to`. function mint(address to, uint256 amount) public override onlyMinter whenNotPaused { _mint(to, amount); emit Minting(to, msg.sender, amount); } // @dev Pauses all token transfers. function pause() public onlyPauser { _pause(); } // @dev Unpauses all token transfers. function unpause() public onlyPauser { _unpause(); } /** * @dev Returns the name of the token. */ function name() public view override(ERC20) returns (string memory) { return _tokenName; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view override(ERC20) returns (string memory) { return _symbol; } function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override(ERC20, ERC20Pausable) { super._beforeTokenTransfer(from, to, amount); } function _transfer( address sender, address recipient, uint256 amount ) internal virtual override whenNotPaused { super._transfer(sender, recipient, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.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 {ERC20PresetMinterPauser}. * * 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, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override 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 this function is * overridden; * * 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 virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual 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. */ 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); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } 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] + 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) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This 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); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(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: * * - `account` 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 += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), 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); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This 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 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 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:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC20.sol"; import "../../../utils/Context.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @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 currentAllowance = allowance(account, _msgSender()); require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance"); unchecked { _approve(account, _msgSender(), currentAllowance - amount); } _burn(account, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC20.sol"; import "../../../security/Pausable.sol"; /** * @dev ERC20 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. */ abstract contract ERC20Pausable is ERC20, Pausable { /** * @dev See {ERC20-_beforeTokenTransfer}. * * Requirements: * * - the contract must not be paused. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override { super._beforeTokenTransfer(from, to, amount); require(!paused(), "ERC20Pausable: token transfer while paused"); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.3; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @title ERC20 Ubiquiti preset interface /// @author Ubiquity Algorithmic Dollar interface IERC20Ubiquity is IERC20 { // ----------- Events ----------- event Minting( address indexed _to, address indexed _minter, uint256 _amount ); event Burning(address indexed _burned, uint256 _amount); // ----------- State changing api ----------- function burn(uint256 amount) external; function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; // ----------- Burner only state changing api ----------- function burnFrom(address account, uint256 amount) external; // ----------- Minter only state changing api ----------- function mint(address account, uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { function hasRole(bytes32 role, address account) external view returns (bool); function getRoleAdmin(bytes32 role) external view returns (bytes32); function grantRole(bytes32 role, address account) external; function revokeRole(bytes32 role, address account) external; function renounceRole(bytes32 role, address account) external; } /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/ */ function _checkRole(bytes32 role, address account) internal view { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { emit RoleAdminChanged(role, getRoleAdmin(role), adminRole); _roles[role].adminRole = adminRole; } function _grantRole(bytes32 role, address account) private { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } function _revokeRole(bytes32 role, address account) private { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.3; import "./IERC20Ubiquity.sol"; /// @title UAD stablecoin interface /// @author Ubiquity Algorithmic Dollar interface IUbiquityAlgorithmicDollar is IERC20Ubiquity { event IncentiveContractUpdate( address indexed _incentivized, address indexed _incentiveContract ); function setIncentiveContract(address account, address incentive) external; function incentiveContract(address account) external view returns (address); }
// SPDX-License-Identifier: MIT // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol. SEE BELOW FOR SOURCE. !! pragma solidity ^0.8.3; interface ICurveFactory { event BasePoolAdded(address base_pool, address implementat); event MetaPoolDeployed( address coin, address base_pool, uint256 A, uint256 fee, address deployer ); function find_pool_for_coins(address _from, address _to) external view returns (address); function find_pool_for_coins( address _from, address _to, uint256 i ) external view returns (address); function get_n_coins(address _pool) external view returns (uint256, uint256); function get_coins(address _pool) external view returns (address[2] memory); function get_underlying_coins(address _pool) external view returns (address[8] memory); function get_decimals(address _pool) external view returns (uint256[2] memory); function get_underlying_decimals(address _pool) external view returns (uint256[8] memory); function get_rates(address _pool) external view returns (uint256[2] memory); function get_balances(address _pool) external view returns (uint256[2] memory); function get_underlying_balances(address _pool) external view returns (uint256[8] memory); function get_A(address _pool) external view returns (uint256); function get_fees(address _pool) external view returns (uint256, uint256); function get_admin_balances(address _pool) external view returns (uint256[2] memory); function get_coin_indices( address _pool, address _from, address _to ) external view returns ( int128, int128, bool ); function add_base_pool( address _base_pool, address _metapool_implementation, address _fee_receiver ) external; function deploy_metapool( address _base_pool, string memory _name, string memory _symbol, address _coin, uint256 _A, uint256 _fee ) external returns (address); function commit_transfer_ownership(address addr) external; function accept_transfer_ownership() external; function set_fee_receiver(address _base_pool, address _fee_receiver) external; function convert_fees() external returns (bool); function admin() external view returns (address); function future_admin() external view returns (address); function pool_list(uint256 arg0) external view returns (address); function pool_count() external view returns (uint256); function base_pool_list(uint256 arg0) external view returns (address); function base_pool_count() external view returns (uint256); function fee_receiver(address arg0) external view returns (address); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.3; import "./interfaces/IMetaPool.sol"; contract TWAPOracle { address public immutable pool; address public immutable token0; address public immutable token1; uint256 public price0Average; uint256 public price1Average; uint256 public pricesBlockTimestampLast; uint256[2] public priceCumulativeLast; constructor( address _pool, address _uADtoken0, address _curve3CRVtoken1 ) { pool = _pool; // coin at index 0 is uAD and index 1 is 3CRV require( IMetaPool(_pool).coins(0) == _uADtoken0 && IMetaPool(_pool).coins(1) == _curve3CRVtoken1, "TWAPOracle: COIN_ORDER_MISMATCH" ); token0 = _uADtoken0; token1 = _curve3CRVtoken1; uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0)); uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1)); // ensure that there's liquidity in the pair require(_reserve0 != 0 && _reserve1 != 0, "TWAPOracle: NO_RESERVES"); // ensure that pair balance is perfect require(_reserve0 == _reserve1, "TWAPOracle: PAIR_UNBALANCED"); priceCumulativeLast = IMetaPool(_pool).get_price_cumulative_last(); pricesBlockTimestampLast = IMetaPool(_pool).block_timestamp_last(); price0Average = 1 ether; price1Average = 1 ether; } // calculate average price function update() external { ( uint256[2] memory priceCumulative, uint256 blockTimestamp ) = _currentCumulativePrices(); if (blockTimestamp - pricesBlockTimestampLast > 0) { // get the balances between now and the last price cumulative snapshot uint256[2] memory twapBalances = IMetaPool(pool).get_twap_balances( priceCumulativeLast, priceCumulative, blockTimestamp - pricesBlockTimestampLast ); // price to exchange amounIn uAD to 3CRV based on TWAP price0Average = IMetaPool(pool).get_dy(0, 1, 1 ether, twapBalances); // price to exchange amounIn 3CRV to uAD based on TWAP price1Average = IMetaPool(pool).get_dy(1, 0, 1 ether, twapBalances); // we update the priceCumulative priceCumulativeLast = priceCumulative; pricesBlockTimestampLast = blockTimestamp; } } // note this will always return 0 before update has been called successfully // for the first time. function consult(address token) external view returns (uint256 amountOut) { if (token == token0) { // price to exchange 1 uAD to 3CRV based on TWAP amountOut = price0Average; } else { require(token == token1, "TWAPOracle: INVALID_TOKEN"); // price to exchange 1 3CRV to uAD based on TWAP amountOut = price1Average; } } function _currentCumulativePrices() internal view returns (uint256[2] memory priceCumulative, uint256 blockTimestamp) { priceCumulative = IMetaPool(pool).get_price_cumulative_last(); blockTimestamp = IMetaPool(pool).block_timestamp_last(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: BSD-4-Clause /* * ABDK Math Quad Smart Contract Library. Copyright © 2019 by ABDK Consulting. * Author: Mikhail Vladimirov <[email protected]> */ pragma solidity ^0.8.0; /** * Smart contract library of mathematical functions operating with IEEE 754 * quadruple-precision binary floating-point numbers (quadruple precision * numbers). As long as quadruple precision numbers are 16-bytes long, they are * represented by bytes16 type. */ library ABDKMathQuad { /* * 0. */ bytes16 private constant _POSITIVE_ZERO = 0x00000000000000000000000000000000; /* * -0. */ bytes16 private constant _NEGATIVE_ZERO = 0x80000000000000000000000000000000; /* * +Infinity. */ bytes16 private constant _POSITIVE_INFINITY = 0x7FFF0000000000000000000000000000; /* * -Infinity. */ bytes16 private constant _NEGATIVE_INFINITY = 0xFFFF0000000000000000000000000000; /* * Canonical NaN value. */ bytes16 private constant NaN = 0x7FFF8000000000000000000000000000; /** * Convert signed 256-bit integer number into quadruple precision number. * * @param x signed 256-bit integer number * @return quadruple precision number */ function fromInt(int256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16(0); else { // We rely on overflow behavior here uint256 result = uint256(x > 0 ? x : -x); uint256 msb = mostSignificantBit(result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ((16383 + msb) << 112); if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16(uint128(result)); } } } /** * Convert quadruple precision number into signed 256-bit integer number * rounding towards zero. Revert on overflow. * * @param x quadruple precision number * @return signed 256-bit integer number */ function toInt(bytes16 x) internal pure returns (int256) { unchecked { uint256 exponent = (uint128(x) >> 112) & 0x7FFF; require(exponent <= 16638); // Overflow if (exponent < 16383) return 0; // Underflow uint256 result = (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | 0x10000000000000000000000000000; if (exponent < 16495) result >>= 16495 - exponent; else if (exponent > 16495) result <<= exponent - 16495; if (uint128(x) >= 0x80000000000000000000000000000000) { // Negative require( result <= 0x8000000000000000000000000000000000000000000000000000000000000000 ); return -int256(result); // We rely on overflow behavior here } else { require( result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ); return int256(result); } } } /** * Convert unsigned 256-bit integer number into quadruple precision number. * * @param x unsigned 256-bit integer number * @return quadruple precision number */ function fromUInt(uint256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16(0); else { uint256 result = x; uint256 msb = mostSignificantBit(result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ((16383 + msb) << 112); return bytes16(uint128(result)); } } } /** * Convert quadruple precision number into unsigned 256-bit integer number * rounding towards zero. Revert on underflow. Note, that negative floating * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer * without error, because they are rounded to zero. * * @param x quadruple precision number * @return unsigned 256-bit integer number */ function toUInt(bytes16 x) internal pure returns (uint256) { unchecked { uint256 exponent = (uint128(x) >> 112) & 0x7FFF; if (exponent < 16383) return 0; // Underflow require(uint128(x) < 0x80000000000000000000000000000000); // Negative require(exponent <= 16638); // Overflow uint256 result = (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | 0x10000000000000000000000000000; if (exponent < 16495) result >>= 16495 - exponent; else if (exponent > 16495) result <<= exponent - 16495; return result; } } /** * Convert signed 128.128 bit fixed point number into quadruple precision * number. * * @param x signed 128.128 bit fixed point number * @return quadruple precision number */ function from128x128(int256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16(0); else { // We rely on overflow behavior here uint256 result = uint256(x > 0 ? x : -x); uint256 msb = mostSignificantBit(result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ((16255 + msb) << 112); if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16(uint128(result)); } } } /** * Convert quadruple precision number into signed 128.128 bit fixed point * number. Revert on overflow. * * @param x quadruple precision number * @return signed 128.128 bit fixed point number */ function to128x128(bytes16 x) internal pure returns (int256) { unchecked { uint256 exponent = (uint128(x) >> 112) & 0x7FFF; require(exponent <= 16510); // Overflow if (exponent < 16255) return 0; // Underflow uint256 result = (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | 0x10000000000000000000000000000; if (exponent < 16367) result >>= 16367 - exponent; else if (exponent > 16367) result <<= exponent - 16367; if (uint128(x) >= 0x80000000000000000000000000000000) { // Negative require( result <= 0x8000000000000000000000000000000000000000000000000000000000000000 ); return -int256(result); // We rely on overflow behavior here } else { require( result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ); return int256(result); } } } /** * Convert signed 64.64 bit fixed point number into quadruple precision * number. * * @param x signed 64.64 bit fixed point number * @return quadruple precision number */ function from64x64(int128 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16(0); else { // We rely on overflow behavior here uint256 result = uint128(x > 0 ? x : -x); uint256 msb = mostSignificantBit(result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = (result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | ((16319 + msb) << 112); if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16(uint128(result)); } } } /** * Convert quadruple precision number into signed 64.64 bit fixed point * number. Revert on overflow. * * @param x quadruple precision number * @return signed 64.64 bit fixed point number */ function to64x64(bytes16 x) internal pure returns (int128) { unchecked { uint256 exponent = (uint128(x) >> 112) & 0x7FFF; require(exponent <= 16446); // Overflow if (exponent < 16319) return 0; // Underflow uint256 result = (uint256(uint128(x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | 0x10000000000000000000000000000; if (exponent < 16431) result >>= 16431 - exponent; else if (exponent > 16431) result <<= exponent - 16431; if (uint128(x) >= 0x80000000000000000000000000000000) { // Negative require(result <= 0x80000000000000000000000000000000); return -int128(int256(result)); // We rely on overflow behavior here } else { require(result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int128(int256(result)); } } } /** * Convert octuple precision number into quadruple precision number. * * @param x octuple precision number * @return quadruple precision number */ function fromOctuple(bytes32 x) internal pure returns (bytes16) { unchecked { bool negative = x & 0x8000000000000000000000000000000000000000000000000000000000000000 > 0; uint256 exponent = (uint256(x) >> 236) & 0x7FFFF; uint256 significand = uint256(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFFF) { if (significand > 0) return NaN; else return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY; } if (exponent > 278526) return negative ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY; else if (exponent < 245649) return negative ? _NEGATIVE_ZERO : _POSITIVE_ZERO; else if (exponent < 245761) { significand = (significand | 0x100000000000000000000000000000000000000000000000000000000000) >> (245885 - exponent); exponent = 0; } else { significand >>= 124; exponent -= 245760; } uint128 result = uint128(significand | (exponent << 112)); if (negative) result |= 0x80000000000000000000000000000000; return bytes16(result); } } /** * Convert quadruple precision number into octuple precision number. * * @param x quadruple precision number * @return octuple precision number */ function toOctuple(bytes16 x) internal pure returns (bytes32) { unchecked { uint256 exponent = (uint128(x) >> 112) & 0x7FFF; uint256 result = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFF) exponent = 0x7FFFF; // Infinity or NaN else if (exponent == 0) { if (result > 0) { uint256 msb = mostSignificantBit(result); result = (result << (236 - msb)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; exponent = 245649 + msb; } } else { result <<= 124; exponent += 245760; } result |= exponent << 236; if (uint128(x) >= 0x80000000000000000000000000000000) result |= 0x8000000000000000000000000000000000000000000000000000000000000000; return bytes32(result); } } /** * Convert double precision number into quadruple precision number. * * @param x double precision number * @return quadruple precision number */ function fromDouble(bytes8 x) internal pure returns (bytes16) { unchecked { uint256 exponent = (uint64(x) >> 52) & 0x7FF; uint256 result = uint64(x) & 0xFFFFFFFFFFFFF; if (exponent == 0x7FF) exponent = 0x7FFF; // Infinity or NaN else if (exponent == 0) { if (result > 0) { uint256 msb = mostSignificantBit(result); result = (result << (112 - msb)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; exponent = 15309 + msb; } } else { result <<= 60; exponent += 15360; } result |= exponent << 112; if (x & 0x8000000000000000 > 0) result |= 0x80000000000000000000000000000000; return bytes16(uint128(result)); } } /** * Convert quadruple precision number into double precision number. * * @param x quadruple precision number * @return double precision number */ function toDouble(bytes16 x) internal pure returns (bytes8) { unchecked { bool negative = uint128(x) >= 0x80000000000000000000000000000000; uint256 exponent = (uint128(x) >> 112) & 0x7FFF; uint256 significand = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFF) { if (significand > 0) return 0x7FF8000000000000; // NaN else return negative ? bytes8(0xFFF0000000000000) // -Infinity : bytes8(0x7FF0000000000000); // Infinity } if (exponent > 17406) return negative ? bytes8(0xFFF0000000000000) // -Infinity : bytes8(0x7FF0000000000000); // Infinity else if (exponent < 15309) return negative ? bytes8(0x8000000000000000) // -0 : bytes8(0x0000000000000000); // 0 else if (exponent < 15361) { significand = (significand | 0x10000000000000000000000000000) >> (15421 - exponent); exponent = 0; } else { significand >>= 60; exponent -= 15360; } uint64 result = uint64(significand | (exponent << 52)); if (negative) result |= 0x8000000000000000; return bytes8(result); } } /** * Test whether given quadruple precision number is NaN. * * @param x quadruple precision number * @return true if x is NaN, false otherwise */ function isNaN(bytes16 x) internal pure returns (bool) { unchecked { return uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF > 0x7FFF0000000000000000000000000000; } } /** * Test whether given quadruple precision number is positive or negative * infinity. * * @param x quadruple precision number * @return true if x is positive or negative infinity, false otherwise */ function isInfinity(bytes16 x) internal pure returns (bool) { unchecked { return uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x7FFF0000000000000000000000000000; } } /** * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x * is positive. Note that sign (-0) is zero. Revert if x is NaN. * * @param x quadruple precision number * @return sign of x */ function sign(bytes16 x) internal pure returns (int8) { unchecked { uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN if (absoluteX == 0) return 0; else if (uint128(x) >= 0x80000000000000000000000000000000) return -1; else return 1; } } /** * Calculate sign (x - y). Revert if either argument is NaN, or both * arguments are infinities of the same sign. * * @param x quadruple precision number * @param y quadruple precision number * @return sign (x - y) */ function cmp(bytes16 x, bytes16 y) internal pure returns (int8) { unchecked { uint128 absoluteX = uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require(absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN uint128 absoluteY = uint128(y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require(absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN // Not infinities of the same sign require(x != y || absoluteX < 0x7FFF0000000000000000000000000000); if (x == y) return 0; else { bool negativeX = uint128(x) >= 0x80000000000000000000000000000000; bool negativeY = uint128(y) >= 0x80000000000000000000000000000000; if (negativeX) { if (negativeY) return absoluteX > absoluteY ? -1 : int8(1); else return -1; } else { if (negativeY) return 1; else return absoluteX > absoluteY ? int8(1) : -1; } } } } /** * Test whether x equals y. NaN, infinity, and -infinity are not equal to * anything. * * @param x quadruple precision number * @param y quadruple precision number * @return true if x equals to y, false otherwise */ function eq(bytes16 x, bytes16 y) internal pure returns (bool) { unchecked { if (x == y) { return uint128(x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF < 0x7FFF0000000000000000000000000000; } else return false; } } /** * Calculate x + y. Special values behave in the following way: * * NaN + x = NaN for any x. * Infinity + x = Infinity for any finite x. * -Infinity + x = -Infinity for any finite x. * Infinity + Infinity = Infinity. * -Infinity + -Infinity = -Infinity. * Infinity + -Infinity = -Infinity + Infinity = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function add(bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; uint256 yExponent = (uint128(y) >> 112) & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) { if (x == y) return x; else return NaN; } else return x; } else if (yExponent == 0x7FFF) return y; else { bool xSign = uint128(x) >= 0x80000000000000000000000000000000; uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; bool ySign = uint128(y) >= 0x80000000000000000000000000000000; uint256 ySignifier = uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return y == _NEGATIVE_ZERO ? _POSITIVE_ZERO : y; else if (ySignifier == 0) return x == _NEGATIVE_ZERO ? _POSITIVE_ZERO : x; else { int256 delta = int256(xExponent) - int256(yExponent); if (xSign == ySign) { if (delta > 112) return x; else if (delta > 0) ySignifier >>= uint256(delta); else if (delta < -112) return y; else if (delta < 0) { xSignifier >>= uint256(-delta); xExponent = yExponent; } xSignifier += ySignifier; if (xSignifier >= 0x20000000000000000000000000000) { xSignifier >>= 1; xExponent += 1; } if (xExponent == 0x7FFF) return xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY; else { if (xSignifier < 0x10000000000000000000000000000) xExponent = 0; else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; return bytes16( uint128( ( xSign ? 0x80000000000000000000000000000000 : 0 ) | (xExponent << 112) | xSignifier ) ); } } else { if (delta > 0) { xSignifier <<= 1; xExponent -= 1; } else if (delta < 0) { ySignifier <<= 1; xExponent = yExponent - 1; } if (delta > 112) ySignifier = 1; else if (delta > 1) ySignifier = ((ySignifier - 1) >> uint256(delta - 1)) + 1; else if (delta < -112) xSignifier = 1; else if (delta < -1) xSignifier = ((xSignifier - 1) >> uint256(-delta - 1)) + 1; if (xSignifier >= ySignifier) xSignifier -= ySignifier; else { xSignifier = ySignifier - xSignifier; xSign = ySign; } if (xSignifier == 0) return _POSITIVE_ZERO; uint256 msb = mostSignificantBit(xSignifier); if (msb == 113) { xSignifier = (xSignifier >> 1) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent += 1; } else if (msb < 112) { uint256 shift = 112 - msb; if (xExponent > shift) { xSignifier = (xSignifier << shift) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent -= shift; } else { xSignifier <<= xExponent - 1; xExponent = 0; } } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0x7FFF) return xSign ? _NEGATIVE_INFINITY : _POSITIVE_INFINITY; else return bytes16( uint128( ( xSign ? 0x80000000000000000000000000000000 : 0 ) | (xExponent << 112) | xSignifier ) ); } } } } } /** * Calculate x - y. Special values behave in the following way: * * NaN - x = NaN for any x. * Infinity - x = Infinity for any finite x. * -Infinity - x = -Infinity for any finite x. * Infinity - -Infinity = Infinity. * -Infinity - Infinity = -Infinity. * Infinity - Infinity = -Infinity - -Infinity = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function sub(bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { return add(x, y ^ 0x80000000000000000000000000000000); } } /** * Calculate x * y. Special values behave in the following way: * * NaN * x = NaN for any x. * Infinity * x = Infinity for any finite positive x. * Infinity * x = -Infinity for any finite negative x. * -Infinity * x = -Infinity for any finite positive x. * -Infinity * x = Infinity for any finite negative x. * Infinity * 0 = NaN. * -Infinity * 0 = NaN. * Infinity * Infinity = Infinity. * Infinity * -Infinity = -Infinity. * -Infinity * Infinity = -Infinity. * -Infinity * -Infinity = Infinity. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function mul(bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; uint256 yExponent = (uint128(y) >> 112) & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) { if (x == y) return x ^ (y & 0x80000000000000000000000000000000); else if (x ^ y == 0x80000000000000000000000000000000) return x | y; else return NaN; } else { if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return x ^ (y & 0x80000000000000000000000000000000); } } else if (yExponent == 0x7FFF) { if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return y ^ (x & 0x80000000000000000000000000000000); } else { uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; uint256 ySignifier = uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; xSignifier *= ySignifier; if (xSignifier == 0) return (x ^ y) & 0x80000000000000000000000000000000 > 0 ? _NEGATIVE_ZERO : _POSITIVE_ZERO; xExponent += yExponent; uint256 msb = xSignifier >= 0x200000000000000000000000000000000000000000000000000000000 ? 225 : xSignifier >= 0x100000000000000000000000000000000000000000000000000000000 ? 224 : mostSignificantBit(xSignifier); if (xExponent + msb < 16496) { // Underflow xExponent = 0; xSignifier = 0; } else if (xExponent + msb < 16608) { // Subnormal if (xExponent < 16496) xSignifier >>= 16496 - xExponent; else if (xExponent > 16496) xSignifier <<= xExponent - 16496; xExponent = 0; } else if (xExponent + msb > 49373) { xExponent = 0x7FFF; xSignifier = 0; } else { if (msb > 112) xSignifier >>= msb - 112; else if (msb < 112) xSignifier <<= 112 - msb; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent = xExponent + msb - 16607; } return bytes16( uint128( uint128( (x ^ y) & 0x80000000000000000000000000000000 ) | (xExponent << 112) | xSignifier ) ); } } } /** * Calculate x / y. Special values behave in the following way: * * NaN / x = NaN for any x. * x / NaN = NaN for any x. * Infinity / x = Infinity for any finite non-negative x. * Infinity / x = -Infinity for any finite negative x including -0. * -Infinity / x = -Infinity for any finite non-negative x. * -Infinity / x = Infinity for any finite negative x including -0. * x / Infinity = 0 for any finite non-negative x. * x / -Infinity = -0 for any finite non-negative x. * x / Infinity = -0 for any finite non-negative x including -0. * x / -Infinity = 0 for any finite non-negative x including -0. * * Infinity / Infinity = NaN. * Infinity / -Infinity = -NaN. * -Infinity / Infinity = -NaN. * -Infinity / -Infinity = NaN. * * Division by zero behaves in the following way: * * x / 0 = Infinity for any finite positive x. * x / -0 = -Infinity for any finite positive x. * x / 0 = -Infinity for any finite negative x. * x / -0 = Infinity for any finite negative x. * 0 / 0 = NaN. * 0 / -0 = NaN. * -0 / 0 = NaN. * -0 / -0 = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function div(bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; uint256 yExponent = (uint128(y) >> 112) & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) return NaN; else return x ^ (y & 0x80000000000000000000000000000000); } else if (yExponent == 0x7FFF) { if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN; else return _POSITIVE_ZERO | ((x ^ y) & 0x80000000000000000000000000000000); } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return _POSITIVE_INFINITY | ((x ^ y) & 0x80000000000000000000000000000000); } else { uint256 ySignifier = uint128(y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) { if (xSignifier != 0) { uint256 shift = 226 - mostSignificantBit(xSignifier); xSignifier <<= shift; xExponent = 1; yExponent += shift - 114; } } else { xSignifier = (xSignifier | 0x10000000000000000000000000000) << 114; } xSignifier = xSignifier / ySignifier; if (xSignifier == 0) return (x ^ y) & 0x80000000000000000000000000000000 > 0 ? _NEGATIVE_ZERO : _POSITIVE_ZERO; assert(xSignifier >= 0x1000000000000000000000000000); uint256 msb = xSignifier >= 0x80000000000000000000000000000 ? mostSignificantBit(xSignifier) : xSignifier >= 0x40000000000000000000000000000 ? 114 : xSignifier >= 0x20000000000000000000000000000 ? 113 : 112; if (xExponent + msb > yExponent + 16497) { // Overflow xExponent = 0x7FFF; xSignifier = 0; } else if (xExponent + msb + 16380 < yExponent) { // Underflow xExponent = 0; xSignifier = 0; } else if (xExponent + msb + 16268 < yExponent) { // Subnormal if (xExponent + 16380 > yExponent) xSignifier <<= xExponent + 16380 - yExponent; else if (xExponent + 16380 < yExponent) xSignifier >>= yExponent - xExponent - 16380; xExponent = 0; } else { // Normal if (msb > 112) xSignifier >>= msb - 112; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent = xExponent + msb + 16269 - yExponent; } return bytes16( uint128( uint128( (x ^ y) & 0x80000000000000000000000000000000 ) | (xExponent << 112) | xSignifier ) ); } } } /** * Calculate -x. * * @param x quadruple precision number * @return quadruple precision number */ function neg(bytes16 x) internal pure returns (bytes16) { unchecked { return x ^ 0x80000000000000000000000000000000; } } /** * Calculate |x|. * * @param x quadruple precision number * @return quadruple precision number */ function abs(bytes16 x) internal pure returns (bytes16) { unchecked { return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; } } /** * Calculate square root of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function sqrt(bytes16 x) internal pure returns (bytes16) { unchecked { if (uint128(x) > 0x80000000000000000000000000000000) return NaN; else { uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; if (xExponent == 0x7FFF) return x; else { uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return _POSITIVE_ZERO; bool oddExponent = xExponent & 0x1 == 0; xExponent = (xExponent + 16383) >> 1; if (oddExponent) { if (xSignifier >= 0x10000000000000000000000000000) xSignifier <<= 113; else { uint256 msb = mostSignificantBit(xSignifier); uint256 shift = (226 - msb) & 0xFE; xSignifier <<= shift; xExponent -= (shift - 112) >> 1; } } else { if (xSignifier >= 0x10000000000000000000000000000) xSignifier <<= 112; else { uint256 msb = mostSignificantBit(xSignifier); uint256 shift = (225 - msb) & 0xFE; xSignifier <<= shift; xExponent -= (shift - 112) >> 1; } } uint256 r = 0x10000000000000000000000000000; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; // Seven iterations should be enough uint256 r1 = xSignifier / r; if (r1 < r) r = r1; return bytes16( uint128( (xExponent << 112) | (r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) ) ); } } } } /** * Calculate binary logarithm of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function log_2(bytes16 x) internal pure returns (bytes16) { unchecked { if (uint128(x) > 0x80000000000000000000000000000000) return NaN; else if (x == 0x3FFF0000000000000000000000000000) return _POSITIVE_ZERO; else { uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; if (xExponent == 0x7FFF) return x; else { uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return _NEGATIVE_INFINITY; bool resultNegative; uint256 resultExponent = 16495; uint256 resultSignifier; if (xExponent >= 0x3FFF) { resultNegative = false; resultSignifier = xExponent - 0x3FFF; xSignifier <<= 15; } else { resultNegative = true; if (xSignifier >= 0x10000000000000000000000000000) { resultSignifier = 0x3FFE - xExponent; xSignifier <<= 15; } else { uint256 msb = mostSignificantBit(xSignifier); resultSignifier = 16493 - msb; xSignifier <<= 127 - msb; } } if (xSignifier == 0x80000000000000000000000000000000) { if (resultNegative) resultSignifier += 1; uint256 shift = 112 - mostSignificantBit(resultSignifier); resultSignifier <<= shift; resultExponent -= shift; } else { uint256 bb = resultNegative ? 1 : 0; while ( resultSignifier < 0x10000000000000000000000000000 ) { resultSignifier <<= 1; resultExponent -= 1; xSignifier *= xSignifier; uint256 b = xSignifier >> 255; resultSignifier += b ^ bb; xSignifier >>= 127 + b; } } return bytes16( uint128( ( resultNegative ? 0x80000000000000000000000000000000 : 0 ) | (resultExponent << 112) | (resultSignifier & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF) ) ); } } } } /** * Calculate natural logarithm of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function ln(bytes16 x) internal pure returns (bytes16) { unchecked { return mul(log_2(x), 0x3FFE62E42FEFA39EF35793C7673007E5); } } /** * Calculate 2^x. * * @param x quadruple precision number * @return quadruple precision number */ function pow_2(bytes16 x) internal pure returns (bytes16) { unchecked { bool xNegative = uint128(x) > 0x80000000000000000000000000000000; uint256 xExponent = (uint128(x) >> 112) & 0x7FFF; uint256 xSignifier = uint128(x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0x7FFF && xSignifier != 0) return NaN; else if (xExponent > 16397) return xNegative ? _POSITIVE_ZERO : _POSITIVE_INFINITY; else if (xExponent < 16255) return 0x3FFF0000000000000000000000000000; else { if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xExponent > 16367) xSignifier <<= xExponent - 16367; else if (xExponent < 16367) xSignifier >>= 16367 - xExponent; if ( xNegative && xSignifier > 0x406E00000000000000000000000000000000 ) return _POSITIVE_ZERO; if ( !xNegative && xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ) return _POSITIVE_INFINITY; uint256 resultExponent = xSignifier >> 128; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xNegative && xSignifier != 0) { xSignifier = ~xSignifier; resultExponent += 1; } uint256 resultSignifier = 0x80000000000000000000000000000000; if (xSignifier & 0x80000000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x16A09E667F3BCC908B2FB1366EA957D3E) >> 128; if (xSignifier & 0x40000000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1306FE0A31B7152DE8D5A46305C85EDEC) >> 128; if (xSignifier & 0x20000000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1172B83C7D517ADCDF7C8C50EB14A791F) >> 128; if (xSignifier & 0x10000000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10B5586CF9890F6298B92B71842A98363) >> 128; if (xSignifier & 0x8000000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1059B0D31585743AE7C548EB68CA417FD) >> 128; if (xSignifier & 0x4000000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x102C9A3E778060EE6F7CACA4F7A29BDE8) >> 128; if (xSignifier & 0x2000000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10163DA9FB33356D84A66AE336DCDFA3F) >> 128; if (xSignifier & 0x1000000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100B1AFA5ABCBED6129AB13EC11DC9543) >> 128; if (xSignifier & 0x800000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10058C86DA1C09EA1FF19D294CF2F679B) >> 128; if (xSignifier & 0x400000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1002C605E2E8CEC506D21BFC89A23A00F) >> 128; if (xSignifier & 0x200000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100162F3904051FA128BCA9C55C31E5DF) >> 128; if (xSignifier & 0x100000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000B175EFFDC76BA38E31671CA939725) >> 128; if (xSignifier & 0x80000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100058BA01FB9F96D6CACD4B180917C3D) >> 128; if (xSignifier & 0x40000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10002C5CC37DA9491D0985C348C68E7B3) >> 128; if (xSignifier & 0x20000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000162E525EE054754457D5995292026) >> 128; if (xSignifier & 0x10000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000B17255775C040618BF4A4ADE83FC) >> 128; if (xSignifier & 0x8000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB) >> 128; if (xSignifier & 0x4000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9) >> 128; if (xSignifier & 0x2000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000162E43F4F831060E02D839A9D16D) >> 128; if (xSignifier & 0x1000000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000B1721BCFC99D9F890EA06911763) >> 128; if (xSignifier & 0x800000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000058B90CF1E6D97F9CA14DBCC1628) >> 128; if (xSignifier & 0x400000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000002C5C863B73F016468F6BAC5CA2B) >> 128; if (xSignifier & 0x200000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000162E430E5A18F6119E3C02282A5) >> 128; if (xSignifier & 0x100000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000B1721835514B86E6D96EFD1BFE) >> 128; if (xSignifier & 0x80000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000058B90C0B48C6BE5DF846C5B2EF) >> 128; if (xSignifier & 0x40000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000002C5C8601CC6B9E94213C72737A) >> 128; if (xSignifier & 0x20000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000162E42FFF037DF38AA2B219F06) >> 128; if (xSignifier & 0x10000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000B17217FBA9C739AA5819F44F9) >> 128; if (xSignifier & 0x8000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000058B90BFCDEE5ACD3C1CEDC823) >> 128; if (xSignifier & 0x4000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000002C5C85FE31F35A6A30DA1BE50) >> 128; if (xSignifier & 0x2000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000162E42FF0999CE3541B9FFFCF) >> 128; if (xSignifier & 0x1000000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000B17217F80F4EF5AADDA45554) >> 128; if (xSignifier & 0x800000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000058B90BFBF8479BD5A81B51AD) >> 128; if (xSignifier & 0x400000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000002C5C85FDF84BD62AE30A74CC) >> 128; if (xSignifier & 0x200000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000162E42FEFB2FED257559BDAA) >> 128; if (xSignifier & 0x100000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000B17217F7D5A7716BBA4A9AE) >> 128; if (xSignifier & 0x80000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000058B90BFBE9DDBAC5E109CCE) >> 128; if (xSignifier & 0x40000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000002C5C85FDF4B15DE6F17EB0D) >> 128; if (xSignifier & 0x20000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000162E42FEFA494F1478FDE05) >> 128; if (xSignifier & 0x10000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000B17217F7D20CF927C8E94C) >> 128; if (xSignifier & 0x8000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000058B90BFBE8F71CB4E4B33D) >> 128; if (xSignifier & 0x4000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000002C5C85FDF477B662B26945) >> 128; if (xSignifier & 0x2000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000162E42FEFA3AE53369388C) >> 128; if (xSignifier & 0x1000000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000B17217F7D1D351A389D40) >> 128; if (xSignifier & 0x800000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000058B90BFBE8E8B2D3D4EDE) >> 128; if (xSignifier & 0x400000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000002C5C85FDF4741BEA6E77E) >> 128; if (xSignifier & 0x200000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000162E42FEFA39FE95583C2) >> 128; if (xSignifier & 0x100000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000B17217F7D1CFB72B45E1) >> 128; if (xSignifier & 0x80000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000058B90BFBE8E7CC35C3F0) >> 128; if (xSignifier & 0x40000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000002C5C85FDF473E242EA38) >> 128; if (xSignifier & 0x20000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000162E42FEFA39F02B772C) >> 128; if (xSignifier & 0x10000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000B17217F7D1CF7D83C1A) >> 128; if (xSignifier & 0x8000000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000058B90BFBE8E7BDCBE2E) >> 128; if (xSignifier & 0x4000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000002C5C85FDF473DEA871F) >> 128; if (xSignifier & 0x2000000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000162E42FEFA39EF44D91) >> 128; if (xSignifier & 0x1000000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000B17217F7D1CF79E949) >> 128; if (xSignifier & 0x800000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000058B90BFBE8E7BCE544) >> 128; if (xSignifier & 0x400000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000002C5C85FDF473DE6ECA) >> 128; if (xSignifier & 0x200000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000162E42FEFA39EF366F) >> 128; if (xSignifier & 0x100000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000B17217F7D1CF79AFA) >> 128; if (xSignifier & 0x80000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000058B90BFBE8E7BCD6D) >> 128; if (xSignifier & 0x40000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000002C5C85FDF473DE6B2) >> 128; if (xSignifier & 0x20000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000162E42FEFA39EF358) >> 128; if (xSignifier & 0x10000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000B17217F7D1CF79AB) >> 128; if (xSignifier & 0x8000000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000058B90BFBE8E7BCD5) >> 128; if (xSignifier & 0x4000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000002C5C85FDF473DE6A) >> 128; if (xSignifier & 0x2000000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000162E42FEFA39EF34) >> 128; if (xSignifier & 0x1000000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000B17217F7D1CF799) >> 128; if (xSignifier & 0x800000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000058B90BFBE8E7BCC) >> 128; if (xSignifier & 0x400000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000002C5C85FDF473DE5) >> 128; if (xSignifier & 0x200000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000162E42FEFA39EF2) >> 128; if (xSignifier & 0x100000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000B17217F7D1CF78) >> 128; if (xSignifier & 0x80000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000058B90BFBE8E7BB) >> 128; if (xSignifier & 0x40000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000002C5C85FDF473DD) >> 128; if (xSignifier & 0x20000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000162E42FEFA39EE) >> 128; if (xSignifier & 0x10000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000B17217F7D1CF6) >> 128; if (xSignifier & 0x8000000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000058B90BFBE8E7A) >> 128; if (xSignifier & 0x4000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000002C5C85FDF473C) >> 128; if (xSignifier & 0x2000000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000162E42FEFA39D) >> 128; if (xSignifier & 0x1000000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000B17217F7D1CE) >> 128; if (xSignifier & 0x800000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000058B90BFBE8E6) >> 128; if (xSignifier & 0x400000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000002C5C85FDF472) >> 128; if (xSignifier & 0x200000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000162E42FEFA38) >> 128; if (xSignifier & 0x100000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000B17217F7D1B) >> 128; if (xSignifier & 0x80000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000058B90BFBE8D) >> 128; if (xSignifier & 0x40000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000002C5C85FDF46) >> 128; if (xSignifier & 0x20000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000162E42FEFA2) >> 128; if (xSignifier & 0x10000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000B17217F7D0) >> 128; if (xSignifier & 0x8000000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000058B90BFBE7) >> 128; if (xSignifier & 0x4000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000002C5C85FDF3) >> 128; if (xSignifier & 0x2000000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000162E42FEF9) >> 128; if (xSignifier & 0x1000000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000B17217F7C) >> 128; if (xSignifier & 0x800000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000058B90BFBD) >> 128; if (xSignifier & 0x400000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000002C5C85FDE) >> 128; if (xSignifier & 0x200000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000162E42FEE) >> 128; if (xSignifier & 0x100000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000B17217F6) >> 128; if (xSignifier & 0x80000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000058B90BFA) >> 128; if (xSignifier & 0x40000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000002C5C85FC) >> 128; if (xSignifier & 0x20000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000162E42FD) >> 128; if (xSignifier & 0x10000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000B17217E) >> 128; if (xSignifier & 0x8000000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000058B90BE) >> 128; if (xSignifier & 0x4000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000002C5C85E) >> 128; if (xSignifier & 0x2000000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000162E42E) >> 128; if (xSignifier & 0x1000000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000B17216) >> 128; if (xSignifier & 0x800000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000058B90A) >> 128; if (xSignifier & 0x400000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000002C5C84) >> 128; if (xSignifier & 0x200000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000162E41) >> 128; if (xSignifier & 0x100000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000000B1720) >> 128; if (xSignifier & 0x80000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000058B8F) >> 128; if (xSignifier & 0x40000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000002C5C7) >> 128; if (xSignifier & 0x20000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000000162E3) >> 128; if (xSignifier & 0x10000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000000B171) >> 128; if (xSignifier & 0x8000 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000000058B8) >> 128; if (xSignifier & 0x4000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000002C5B) >> 128; if (xSignifier & 0x2000 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000000162D) >> 128; if (xSignifier & 0x1000 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000B16) >> 128; if (xSignifier & 0x800 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000000058A) >> 128; if (xSignifier & 0x400 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000000002C4) >> 128; if (xSignifier & 0x200 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000161) >> 128; if (xSignifier & 0x100 > 0) resultSignifier = (resultSignifier * 0x1000000000000000000000000000000B0) >> 128; if (xSignifier & 0x80 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000057) >> 128; if (xSignifier & 0x40 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000000002B) >> 128; if (xSignifier & 0x20 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000015) >> 128; if (xSignifier & 0x10 > 0) resultSignifier = (resultSignifier * 0x10000000000000000000000000000000A) >> 128; if (xSignifier & 0x8 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000004) >> 128; if (xSignifier & 0x4 > 0) resultSignifier = (resultSignifier * 0x100000000000000000000000000000001) >> 128; if (!xNegative) { resultSignifier = (resultSignifier >> 15) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; resultExponent += 0x3FFF; } else if (resultExponent <= 0x3FFE) { resultSignifier = (resultSignifier >> 15) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; resultExponent = 0x3FFF - resultExponent; } else { resultSignifier = resultSignifier >> (resultExponent - 16367); resultExponent = 0; } return bytes16(uint128((resultExponent << 112) | resultSignifier)); } } } /** * Calculate e^x. * * @param x quadruple precision number * @return quadruple precision number */ function exp(bytes16 x) internal pure returns (bytes16) { unchecked { return pow_2(mul(x, 0x3FFF71547652B82FE1777D0FFDA0D23A)); } } /** * Get index of the most significant non-zero bit in binary representation of * x. Reverts if x is zero. * * @return index of the most significant non-zero bit in binary representation * of x */ function mostSignificantBit(uint256 x) private pure returns (uint256) { unchecked { require(x > 0); uint256 result = 0; if (x >= 0x100000000000000000000000000000000) { x >>= 128; result += 128; } if (x >= 0x10000000000000000) { x >>= 64; result += 64; } if (x >= 0x100000000) { x >>= 32; result += 32; } if (x >= 0x10000) { x >>= 16; result += 16; } if (x >= 0x100) { x >>= 8; result += 8; } if (x >= 0x10) { x >>= 4; result += 4; } if (x >= 0x4) { x >>= 2; result += 2; } if (x >= 0x2) result += 1; // No need to shift x anymore return result; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC1155.sol"; import "./IERC1155Receiver.sol"; import "./extensions/IERC1155MetadataURI.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { using Address for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: balance query for the zero address"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(_msgSender() != operator, "ERC1155: setting approval status for self"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not owner nor approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: transfer caller is not owner nor approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`. * * Emits a {TransferSingle} event. * * Requirements: * * - `account` cannot be the zero address. * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address account, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(account != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data); _balances[id][account] += amount; emit TransferSingle(operator, address(0), account, id, amount); _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `account` * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens of token type `id`. */ function _burn( address account, uint256 id, uint256 amount ) internal virtual { require(account != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), ""); uint256 accountBalance = _balances[id][account]; require(accountBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][account] = accountBalance - amount; } emit TransferSingle(operator, account, address(0), id, amount); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address account, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(account != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, account, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 accountBalance = _balances[id][account]; require(accountBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][account] = accountBalance - amount; } } emit TransferBatch(operator, account, address(0), ids, amounts); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver(to).onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC1155.sol"; /** * @dev Extension of {ERC1155} that allows token holders to destroy both their * own tokens and those that they have been approved to use. * * _Available since v3.1._ */ abstract contract ERC1155Burnable is ERC1155 { function burn( address account, uint256 id, uint256 value ) public virtual { require( account == _msgSender() || isApprovedForAll(account, _msgSender()), "ERC1155: caller is not owner nor approved" ); _burn(account, id, value); } function burnBatch( address account, uint256[] memory ids, uint256[] memory values ) public virtual { require( account == _msgSender() || isApprovedForAll(account, _msgSender()), "ERC1155: caller is not owner nor approved" ); _burnBatch(account, ids, values); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC1155.sol"; import "../../../security/Pausable.sol"; /** * @dev ERC1155 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. * * _Available since v3.1._ */ abstract contract ERC1155Pausable is ERC1155, Pausable { /** * @dev See {ERC1155-_beforeTokenTransfer}. * * Requirements: * * - the contract must not be paused. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); require(!paused(), "ERC1155Pausable: token transfer while paused"); } }
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: EUPL V1.2 pragma solidity ^0.8.3; /** * @dev Wrappers over Solidity's array push operations with added check * */ library SafeAddArray { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * */ function add(bytes32[] storage array, bytes32 value) internal { for (uint256 i; i < array.length; i++) { if (array[i] == value) { return; } } array.push(value); } function add(string[] storage array, string memory value) internal { bytes32 hashValue = keccak256(bytes(value)); for (uint256 i; i < array.length; i++) { if (keccak256(bytes(array[i])) == hashValue) { return; } } array.push(value); } function add(uint256[] storage array, uint256 value) internal { for (uint256 i; i < array.length; i++) { if (array[i] == value) { return; } } array.push(value); } function add(uint256[] storage array, uint256[] memory values) internal { for (uint256 i; i < values.length; i++) { bool exist = false; for (uint256 j; j < array.length; j++) { if (array[j] == values[i]) { exist = true; break; } } if (!exist) { array.push(values[i]); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** @dev Handles the receipt of a single ERC1155 token type. This function is called at the end of a `safeTransferFrom` after the balance has been updated. To accept the transfer, this must return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61, or its own function selector). @param operator The address which initiated the transfer (i.e. msg.sender) @param from The address which previously owned the token @param id The ID of the token being transferred @param value The amount of tokens being transferred @param data Additional data with no specified format @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** @dev Handles the receipt of a multiple ERC1155 token types. This function is called at the end of a `safeBatchTransferFrom` after the balances have been updated. To accept the transfer(s), this must return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81, or its own function selector). @param operator The address which initiated the batch transfer (i.e. msg.sender) @param from The address which previously owned the token @param ids An array containing ids of each token being transferred (order and length must match values array) @param values An array containing amounts of each token being transferred (order and length must match ids array) @param data Additional data with no specified format @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.3; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./interfaces/IERC20Ubiquity.sol"; import "./UbiquityAlgorithmicDollarManager.sol"; import "./interfaces/ITWAPOracle.sol"; import "./BondingShareV2.sol"; import "./interfaces/IUbiquityFormulas.sol"; import "./interfaces/IERC1155Ubiquity.sol"; contract MasterChefV2 { using SafeERC20 for IERC20Ubiquity; using SafeERC20 for IERC20; // Info of each user. struct BondingShareInfo { uint256 amount; // bonding rights. uint256 rewardDebt; // Reward debt. See explanation below. // // We do some fancy math here. Basically, any point in time, the amount of uGOVs // entitled to a user but is pending to be distributed is: // // pending reward = (user.amount * pool.accuGOVPerShare) - user.rewardDebt // // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: // 1. The pool's `accuGOVPerShare` (and `lastRewardBlock`) gets updated. // 2. User receives the pending reward sent to his/her address. // 3. User's `amount` gets updated. // 4. User's `rewardDebt` gets updated. } // Info of each pool. struct PoolInfo { uint256 lastRewardBlock; // Last block number that uGOVs distribution occurs. uint256 accuGOVPerShare; // Accumulated uGOVs per share, times 1e12. See below. } uint256 private _totalShares; // Ubiquity Manager UbiquityAlgorithmicDollarManager public manager; // uGOV tokens created per block. uint256 public uGOVPerBlock = 1e18; // Bonus muliplier for early uGOV makers. uint256 public uGOVmultiplier = 1e18; uint256 public minPriceDiffToUpdateMultiplier = 1000000000000000; uint256 public lastPrice = 1 ether; uint256 public uGOVDivider; // Info of each pool. PoolInfo public pool; // Info of each user that stakes LP tokens. mapping(uint256 => BondingShareInfo) private _bsInfo; event Deposit( address indexed user, uint256 amount, uint256 indexed bondingShareId ); event Withdraw( address indexed user, uint256 amount, uint256 indexed bondingShareId ); // ----------- Modifiers ----------- modifier onlyTokenManager() { require( manager.hasRole(manager.UBQ_TOKEN_MANAGER_ROLE(), msg.sender), "MasterChef: not UBQ manager" ); _; } modifier onlyBondingContract() { require( msg.sender == manager.bondingContractAddress(), "MasterChef: not Bonding Contract" ); _; } constructor(address _manager) { manager = UbiquityAlgorithmicDollarManager(_manager); pool.lastRewardBlock = block.number; pool.accuGOVPerShare = 0; // uint256(1e12); uGOVDivider = 5; // 100 / 5 = 20% extra minted ugov for treasury _updateUGOVMultiplier(); } function setUGOVPerBlock(uint256 _uGOVPerBlock) external onlyTokenManager { uGOVPerBlock = _uGOVPerBlock; } // the bigger uGOVDivider is the less extra Ugov will be minted for the treasury function setUGOVShareForTreasury(uint256 _uGOVDivider) external onlyTokenManager { uGOVDivider = _uGOVDivider; } function setMinPriceDiffToUpdateMultiplier( uint256 _minPriceDiffToUpdateMultiplier ) external onlyTokenManager { minPriceDiffToUpdateMultiplier = _minPriceDiffToUpdateMultiplier; } // Deposit LP tokens to MasterChef for uGOV allocation. function deposit( address to, uint256 _amount, uint256 _bondingShareID ) external onlyBondingContract { BondingShareInfo storage bs = _bsInfo[_bondingShareID]; _updatePool(); if (bs.amount > 0) { uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) - bs.rewardDebt; _safeUGOVTransfer(to, pending); } bs.amount += _amount; bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12; _totalShares += _amount; emit Deposit(to, _amount, _bondingShareID); } // Withdraw LP tokens from MasterChef. function withdraw( address to, uint256 _amount, uint256 _bondingShareID ) external onlyBondingContract { BondingShareInfo storage bs = _bsInfo[_bondingShareID]; require(bs.amount >= _amount, "MC: amount too high"); _updatePool(); uint256 pending = ((bs.amount * pool.accuGOVPerShare) / 1e12) - bs.rewardDebt; // send UGOV to Bonding Share holder _safeUGOVTransfer(to, pending); bs.amount -= _amount; bs.rewardDebt = (bs.amount * pool.accuGOVPerShare) / 1e12; _totalShares -= _amount; emit Withdraw(to, _amount, _bondingShareID); } /// @dev get pending uGOV rewards from MasterChef. /// @return amount of pending rewards transfered to msg.sender /// @notice only send pending rewards function getRewards(uint256 bondingShareID) external returns (uint256) { require( IERC1155Ubiquity(manager.bondingShareAddress()).balanceOf( msg.sender, bondingShareID ) == 1, "MS: caller is not owner" ); // calculate user reward BondingShareInfo storage user = _bsInfo[bondingShareID]; _updatePool(); uint256 pending = ((user.amount * pool.accuGOVPerShare) / 1e12) - user.rewardDebt; _safeUGOVTransfer(msg.sender, pending); user.rewardDebt = (user.amount * pool.accuGOVPerShare) / 1e12; return pending; } // View function to see pending uGOVs on frontend. function pendingUGOV(uint256 bondingShareID) external view returns (uint256) { BondingShareInfo storage user = _bsInfo[bondingShareID]; uint256 accuGOVPerShare = pool.accuGOVPerShare; uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress()) .totalSupply(); if (block.number > pool.lastRewardBlock && lpSupply != 0) { uint256 multiplier = _getMultiplier(); uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18; accuGOVPerShare = accuGOVPerShare + ((uGOVReward * 1e12) / lpSupply); } return (user.amount * accuGOVPerShare) / 1e12 - user.rewardDebt; } /** * @dev get the amount of shares and the reward debt of a bonding share . */ function getBondingShareInfo(uint256 _id) external view returns (uint256[2] memory) { return [_bsInfo[_id].amount, _bsInfo[_id].rewardDebt]; } /** * @dev Total amount of shares . */ function totalShares() external view virtual returns (uint256) { return _totalShares; } // UPDATE uGOV multiplier function _updateUGOVMultiplier() internal { // (1.05/(1+abs(1-TWAP_PRICE))) uint256 currentPrice = _getTwapPrice(); bool isPriceDiffEnough = false; // a minimum price variation is needed to update the multiplier if (currentPrice > lastPrice) { isPriceDiffEnough = currentPrice - lastPrice > minPriceDiffToUpdateMultiplier; } else { isPriceDiffEnough = lastPrice - currentPrice > minPriceDiffToUpdateMultiplier; } if (isPriceDiffEnough) { uGOVmultiplier = IUbiquityFormulas(manager.formulasAddress()) .ugovMultiply(uGOVmultiplier, currentPrice); lastPrice = currentPrice; } } // Update reward variables of the given pool to be up-to-date. function _updatePool() internal { if (block.number <= pool.lastRewardBlock) { return; } _updateUGOVMultiplier(); uint256 lpSupply = IERC1155Ubiquity(manager.bondingShareAddress()) .totalSupply(); if (lpSupply == 0) { pool.lastRewardBlock = block.number; return; } uint256 multiplier = _getMultiplier(); uint256 uGOVReward = (multiplier * uGOVPerBlock) / 1e18; IERC20Ubiquity(manager.governanceTokenAddress()).mint( address(this), uGOVReward ); // mint another x% for the treasury IERC20Ubiquity(manager.governanceTokenAddress()).mint( manager.treasuryAddress(), uGOVReward / uGOVDivider ); pool.accuGOVPerShare = pool.accuGOVPerShare + ((uGOVReward * 1e12) / lpSupply); pool.lastRewardBlock = block.number; } // Safe uGOV transfer function, just in case if rounding // error causes pool to not have enough uGOVs. function _safeUGOVTransfer(address _to, uint256 _amount) internal { IERC20Ubiquity uGOV = IERC20Ubiquity(manager.governanceTokenAddress()); uint256 uGOVBal = uGOV.balanceOf(address(this)); if (_amount > uGOVBal) { uGOV.safeTransfer(_to, uGOVBal); } else { uGOV.safeTransfer(_to, _amount); } } function _getMultiplier() internal view returns (uint256) { return (block.number - pool.lastRewardBlock) * uGOVmultiplier; } function _getTwapPrice() internal view returns (uint256) { return ITWAPOracle(manager.twapOracleAddress()).consult( manager.dollarTokenAddress() ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.3; interface ICollectableDust { event DustSent(address _to, address token, uint256 amount); event ProtocolTokenAdded(address _token); event ProtocolTokenRemoved(address _token); function addProtocolToken(address _token) external; function removeProtocolToken(address _token) external; function sendDust( address _to, address _token, uint256 _amount ) external; }
{ "optimizer": { "enabled": true, "runs": 800 }, "metadata": { "bytecodeHash": "none", "useLiteralContent": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"address","name":"_bondingFormulasAddress","type":"address"},{"internalType":"address[]","name":"_originals","type":"address[]"},{"internalType":"uint256[]","name":"_lpBalances","type":"uint256[]"},{"internalType":"uint256[]","name":"_weeks","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"uint256","name":"_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lpAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_bondingShareAmount","type":"uint256"}],"name":"AddLiquidityFromBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_blockCountInAWeek","type":"uint256"}],"name":"BlockCountInAWeekUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_bondingDiscountMultiplier","type":"uint256"}],"name":"BondingDiscountMultiplierUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"uint256","name":"_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lpAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_bondingShareAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_weeks","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_endBlock","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DustSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"uint256","name":"_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lpsAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_sharesAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_weeks","type":"uint256"}],"name":"Migrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_tokenWithdrawn","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amountWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_amountTransfered","type":"uint256"}],"name":"PriceReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"}],"name":"ProtocolTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"}],"name":"ProtocolTokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":true,"internalType":"uint256","name":"_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lpAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lpAmountTransferred","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_lprewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_bondingShareAmount","type":"uint256"}],"name":"RemoveLiquidityFromBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"ETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accLpRewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"_weeks","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"addProtocolToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_original","type":"address"},{"internalType":"uint256","name":"_lpBalance","type":"uint256"},{"internalType":"uint256","name":"_weeks","type":"uint256"}],"name":"addUserToMigrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blockCountInAWeek","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondingDiscountMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondingFormulasAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"crvPriceReset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentShareValue","outputs":[{"internalType":"uint256","name":"priceShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"data","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lpsAmount","type":"uint256"},{"internalType":"uint256","name":"_weeks","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lpRewardDebt","type":"uint256"}],"name":"lpRewardForShares","outputs":[{"internalType":"uint256","name":"pendingLpReward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"contract UbiquityAlgorithmicDollarManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrate","outputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrating","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"pendingLpRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeProtocolToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendDust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockCountInAWeek","type":"uint256"}],"name":"setBlockCountInAWeek","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bondingDiscountMultiplier","type":"uint256"}],"name":"setBondingDiscountMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bondingFormulasAddress","type":"address"}],"name":"setBondingFormulasAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_migrating","type":"bool"}],"name":"setMigrating","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_migrator","type":"address"}],"name":"setMigrator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"toMigrateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLpToMigrate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"uADPriceReset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040819052600060808190526200001b91600391620002b8565b5066038d7ea4c6800060055561b13160065560006007556010805460ff191690553480156200004957600080fd5b506040516200627c3803806200627c8339810160408190526200006c9162000487565b6002805460ff19169055600480546001600160a01b038088166001600160a01b031992831617909255600a805492871692821692909217909155600b805490911633179055825180620001065760405162461bcd60e51b815260206004820152601360248201527f6164647265737320617272617920656d7074790000000000000000000000000060448201526064015b60405180910390fd5b82518114620001585760405162461bcd60e51b815260206004820152601e60248201527f62616c616e636573206172726179206e6f742073616d65206c656e67746800006044820152606401620000fd565b81518114620001aa5760405162461bcd60e51b815260206004820152601b60248201527f7765656b73206172726179206e6f742073616d65206c656e67746800000000006044820152606401620000fd565b8351620001bf90600c90602087019062000347565b508251620001d590600d9060208601906200039f565b508151620001eb90600e9060208501906200039f565b5060005b81811015620002ab5762000205816001620005fe565b600f60008784815181106200022a57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508381815181106200027757634e487b7160e01b600052603260045260246000fd5b602002602001015160096000828254620002929190620005fe565b90915550620002a390508162000656565b9050620001ef565b50505050505050620006a0565b828054620002c69062000619565b90600052602060002090601f016020900481019282620002ea576000855562000335565b82601f106200030557805160ff191683800117855562000335565b8280016001018555821562000335579182015b828111156200033557825182559160200191906001019062000318565b5062000343929150620003dc565b5090565b82805482825590600052602060002090810192821562000335579160200282015b828111156200033557825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019062000368565b8280548282559060005260206000209081019282156200033557916020028201828111156200033557825182559160200191906001019062000318565b5b80821115620003435760008155600101620003dd565b80516001600160a01b03811681146200040b57600080fd5b919050565b600082601f83011262000421578081fd5b815160206200043a6200043483620005d8565b620005a5565b80838252828201915082860187848660051b89010111156200045a578586fd5b855b858110156200047a578151845292840192908401906001016200045c565b5090979650505050505050565b600080600080600060a086880312156200049f578081fd5b620004aa86620003f3565b94506020620004bb818801620003f3565b60408801519095506001600160401b0380821115620004d8578384fd5b818901915089601f830112620004ec578384fd5b8151620004fd6200043482620005d8565b8082825285820191508585018d878560051b88010111156200051d578788fd5b8795505b838610156200054a576200053581620003f3565b83526001959095019491860191860162000521565b5060608c0151909850945050508083111562000564578384fd5b620005728a848b0162000410565b9450608089015192508083111562000588578384fd5b5050620005988882890162000410565b9150509295509295909350565b604051601f8201601f191681016001600160401b0381118282101715620005d057620005d06200068a565b604052919050565b60006001600160401b03821115620005f457620005f46200068a565b5060051b60200190565b6000821982111562000614576200061462000674565b500190565b600181811c908216806200062e57607f821691505b602082108114156200065057634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156200066d576200066d62000674565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b615bcc80620006b06000396000f3fe60806040526004361061021d5760003560e01c80638f88f38d1161011d578063bf0d68e4116100b0578063dc0c00c41161007f578063f785f03d11610064578063f785f03d146105e0578063f941717d14610600578063fa3305c91461062d57610224565b8063dc0c00c4146105a0578063e2bbb158146105c057610224565b8063bf0d68e414610524578063c2ee3a0814610544578063c5d1cb6314610560578063cd6c212b1461058057610224565b8063a734f06e116100ec578063a734f06e146104b1578063aa1ec70a146104d9578063aadc68a5146104ef578063b167d4ea1461050457610224565b80638f88f38d146104465780638fd3ab801461045c5780639d7de6b314610471578063a194bcde1461049157610224565b8063481c6a75116101b057806365566d651161017f5780637cc6bd41116101645780637cc6bd41146103f15780637cd07e47146104115780638456cb591461043157610224565b806365566d65146103b957806373d4a13a146103cf57610224565b8063481c6a751461031f5780634956cf1c1461035757806352159150146103815780635c975abb146103a157610224565b80632f72589e116101ec5780632f72589e146102aa5780633b1ba367146102ca5780633f4ba83a146102ea578063422f1043146102ff57610224565b80630c76214114610229578063118c03ec1461025257806323cf3118146102685780632db8c1291461028a57610224565b3661022457005b600080fd5b34801561023557600080fd5b5061023f60085481565b6040519081526020015b60405180910390f35b34801561025e57600080fd5b5061023f60095481565b34801561027457600080fd5b5061028861028336600461576b565b61064d565b005b34801561029657600080fd5b506102886102a53660046157a3565b6106ca565b3480156102b657600080fd5b506102886102c5366004615933565b61080d565b3480156102d657600080fd5b506102886102e5366004615933565b61097c565b3480156102f657600080fd5b50610288611011565b34801561030b57600080fd5b5061028861031a36600461596c565b61114d565b34801561032b57600080fd5b5060045461033f906001600160a01b031681565b6040516001600160a01b039091168152602001610249565b34801561036357600080fd5b506010546103719060ff1681565b6040519015158152602001610249565b34801561038d57600080fd5b5061023f61039c366004615933565b611911565b3480156103ad57600080fd5b5060025460ff16610371565b3480156103c557600080fd5b5061023f60075481565b3480156103db57600080fd5b506103e4611eaf565b60405161024991906159df565b3480156103fd57600080fd5b5061028861040c366004615933565b611f3d565b34801561041d57600080fd5b50600b5461033f906001600160a01b031681565b34801561043d57600080fd5b5061028861256c565b34801561045257600080fd5b5061023f60055481565b34801561046857600080fd5b5061023f6126a6565b34801561047d57600080fd5b5061028861048c36600461594b565b612804565b34801561049d57600080fd5b506102886104ac366004615933565b613150565b3480156104bd57600080fd5b5061033f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156104e557600080fd5b5061023f60065481565b3480156104fb57600080fd5b5061023f6132b8565b34801561051057600080fd5b5061028861051f3660046157e3565b6135ba565b34801561053057600080fd5b5061028861053f36600461576b565b6136f1565b34801561055057600080fd5b5061023f670de0b6b3a764000081565b34801561056c57600080fd5b5061023f61057b36600461594b565b613830565b34801561058c57600080fd5b50600a5461033f906001600160a01b031681565b3480156105ac57600080fd5b506102886105bb36600461576b565b61386d565b3480156105cc57600080fd5b5061023f6105db36600461594b565b6139cf565b3480156105ec57600080fd5b506102886105fb36600461587d565b613e4c565b34801561060c57600080fd5b5061023f61061b36600461576b565b600f6020526000908152604090205481565b34801561063957600080fd5b5061028861064836600461576b565b613ea8565b600b546001600160a01b0316331461069b5760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b60448201526064015b60405180910390fd5b600b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561071657600080fd5b505afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e91906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561078b57600080fd5b505afa15801561079f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c39190615899565b6107fd5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b610808838383613fe4565b505050565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561085957600080fd5b505afa15801561086d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156108ce57600080fd5b505afa1580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190615899565b6109405760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b60068190556040518181527f3a1c0b7d3cdecbab83b82697d51cbcdb308b3bbae63e597cbc958deb9c830e50906020015b60405180910390a150565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b1580156109c857600080fd5b505afa1580156109dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0091906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a3d57600080fd5b505afa158015610a51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a759190615899565b610aaf5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610aff57600080fd5b505afa158015610b13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b379190615787565b604051630d2680e960e11b815260048101849052600060248201819052604482018190529192506001600160a01b03831690631a4d01d290606401602060405180830381600087803b158015610b8c57600080fd5b505af1158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc491906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610c1457600080fd5b505afa158015610c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4c9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610c8657600080fd5b505af1158015610c9a573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610cee57600080fd5b505afa158015610d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d269190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610d6757600080fd5b505afa158015610d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9f91906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e279190615787565b6001600160a01b031663a9059cbb600460009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e8357600080fd5b505afa158015610e97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebb9190615787565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b158015610f0357600080fd5b505af1158015610f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3b9190615899565b507f621af463096d58966fa48f497088db472e960b9f399d8cbf787ec0f7d2253365600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b505afa158015610fbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe39190615787565b604080516001600160a01b03909216825260208201859052810183905260600160405180910390a150505050565b600480546040805163e63ab1e960e01b815290516001600160a01b03909216926391d1485492849263e63ab1e99281810192602092909190829003018186803b15801561105d57600080fd5b505afa158015611071573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109591906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156110d257600080fd5b505afa1580156110e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110a9190615899565b6111435760405162461bcd60e51b815260206004820152600a6024820152693737ba103830bab9b2b960b11b6044820152606401610692565b61114b614195565b565b60025460ff16156111935760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b60008061119f84614231565b815191935091506111ae61470a565b60006111be828460600151613830565b9050306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111f957600080fd5b505afa15801561120d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112319190615787565b6001600160a01b031663d5a8cf648486846040518463ffffffff1660e01b8152600401611260939291906159f2565b60206040518083038186803b15801561127857600080fd5b505afa15801561128c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b091906158b5565b9050808360a0018181516112c49190615ab1565b905250600880548291906000906112dc908490615b08565b92505081905550611380333089600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561133757600080fd5b505afa15801561134b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136f9190615787565b6001600160a01b0316929190614afd565b868360a0018181516113929190615ab1565b9052506004805460408051630110f17360e51b815290516001600160a01b039092169263221e2e60928282019260209290829003018186803b1580156113d757600080fd5b505afa1580156113eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140f9190615787565b604051635ae2fb3960e11b815233600482015260248101849052604481018890526001600160a01b03919091169063b5c5f67290606401600060405180830381600087803b15801561146057600080fd5b505af1158015611474573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c857600080fd5b505afa1580156114dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115009190615787565b60a085015160055460405163016cdd2960e61b815260048101929092526024820189905260448201526001600160a01b039190911690635b374a409060640160206040518083038186803b15801561155757600080fd5b505afa15801561156b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158f91906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156115df57600080fd5b505afa1580156115f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116179190615787565b604051630efe6a8b60e01b815233600482015260248101839052604481018990526001600160a01b039190911690630efe6a8b90606401600060405180830381600087803b15801561166857600080fd5b505af115801561167c573d6000803e3d6000fd5b505050506006548661168e9190615ae9565b6116989043615ab1565b60808501526116a561470a565b64e8d4a51000600754600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156116fc57600080fd5b505afa158015611710573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117349190615787565b6001600160a01b0316637b80a5c08a6040518263ffffffff1660e01b815260040161176191815260200190565b604080518083038186803b15801561177857600080fd5b505afa15801561178c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b09190615817565b516117bb9190615ae9565b6117c59190615ac9565b6060850152600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b15801561180c57600080fd5b505afa158015611820573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118449190615787565b60a0850151606086015160808701516040516353ab9e7560e11b8152600481018c90526024810193909352604483019190915260648201526001600160a01b03919091169063a7573cea90608401600060405180830381600087803b1580156118ac57600080fd5b505af11580156118c0573d6000803e3d6000fd5b50505060a0850151604080519182526020820184905289925033917f4419681a20e94d59aaa91e563559dc52e7fb9ec1540b072ce92014f31961ce0091015b60405180910390a35050505050505050565b600480546040805163310c7a0f60e21b8152905160009384936001600160a01b03169263c431e83c9281830192602092829003018186803b15801561195557600080fd5b505afa158015611969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198d9190615787565b604051636c7f3b2160e11b8152600481018590529091506000906001600160a01b0383169063d8fe76429060240160c06040518083038186803b1580156119d357600080fd5b505afa1580156119e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0b91906158cd565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5d57600080fd5b505afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615787565b6001600160a01b0316637b80a5c0866040518263ffffffff1660e01b8152600401611ac291815260200190565b604080518083038186803b158015611ad957600080fd5b505afa158015611aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b119190615817565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b6357600080fd5b505afa158015611b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9b9190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015611bdc57600080fd5b505afa158015611bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1491906158b5565b9050600954846001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c5257600080fd5b505afa158015611c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8a91906158b5565b611c949190615ab1565b8110611ea1576000600954856001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cd857600080fd5b505afa158015611cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1091906158b5565b611d1a9190615ab1565b611d249083615b08565b60075460085491925090821115611e6757600060085483611d459190615b08565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015611d9557600080fd5b505afa158015611da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcd9190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b158015611e0557600080fd5b505afa158015611e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3d91906158b5565b611e4c8264e8d4a51000615ae9565b611e569190615ac9565b600754611e639190615ab1565b9150505b6060850151845164e8d4a5100090611e80908490615ae9565b611e8a9190615ac9565b611e949190615b08565b9650505050505050611eaa565b60009450505050505b919050565b60038054611ebc90615b4b565b80601f0160208091040260200160405190810160405280929190818152602001828054611ee890615b4b565b8015611f355780601f10611f0a57610100808354040283529160200191611f35565b820191906000526020600020905b815481529060010190602001808311611f1857829003601f168201915b505050505081565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b158015611f8957600080fd5b505afa158015611f9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015611ffe57600080fd5b505afa158015612012573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120369190615899565b6120705760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156120c057600080fd5b505afa1580156120d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f89190615787565b604051630d2680e960e11b815260048101849052600160248201526000604482018190529192506001600160a01b03831690631a4d01d290606401602060405180830381600087803b15801561214d57600080fd5b505af1158015612161573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218591906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b1580156121d557600080fd5b505afa1580156121e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220d9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561224757600080fd5b505af115801561225b573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156122af57600080fd5b505afa1580156122c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e79190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561232857600080fd5b505afa15801561233c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236091906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156123b057600080fd5b505afa1580156123c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e89190615787565b6001600160a01b031663a9059cbb600460009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b15801561244457600080fd5b505afa158015612458573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247c9190615787565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b1580156124c457600080fd5b505af11580156124d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fc9190615899565b507f621af463096d58966fa48f497088db472e960b9f399d8cbf787ec0f7d2253365600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b600480546040805163e63ab1e960e01b815290516001600160a01b03909216926391d1485492849263e63ab1e99281810192602092909190829003018186803b1580156125b857600080fd5b505afa1580156125cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f091906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561262d57600080fd5b505afa158015612641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126659190615899565b61269e5760405162461bcd60e51b815260206004820152600a6024820152693737ba103830bab9b2b960b11b6044820152606401610692565b61114b614b7d565b60105460009060ff166126fb5760405162461bcd60e51b815260206004820152601060248201527f6e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610692565b50336000908152600f60205260409020548061274a5760405162461bcd60e51b815260206004820152600e60248201526d6e6f74207631206164647265737360901b6044820152606401610692565b612800600c61275a600184615b08565b8154811061277857634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316600d61279a600185615b08565b815481106127b857634e487b7160e01b600052603260045260246000fd5b9060005260206000200154600e6001856127d29190615b08565b815481106127f057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154614bf8565b5090565b60025460ff161561284a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b60008061285683614231565b91509150838160a0015110156128ae5760405162461bcd60e51b815260206004820152601760248201527f426f6e64696e673a20616d6f756e7420746f6f206269670000000000000000006044820152606401610692565b6000306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156128e957600080fd5b505afa1580156128fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129219190615787565b6001600160a01b031663629056cb8385886040518463ffffffff1660e01b8152600401612950939291906159f2565b60206040518083038186803b15801561296857600080fd5b505afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a091906158b5565b90506129aa61470a565b825160608301516000916129bd91613830565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015612a0d57600080fd5b505afa158015612a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a459190615787565b604051635ae2fb3960e11b815233600482015260248101849052604481018790526001600160a01b03919091169063b5c5f67290606401600060405180830381600087803b158015612a9657600080fd5b505af1158015612aaa573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015612afe57600080fd5b505afa158015612b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b369190615787565b9050306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612b7157600080fd5b505afa158015612b85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba99190615787565b6001600160a01b031663a64154f08587856040518463ffffffff1660e01b8152600401612bd8939291906159f2565b60206040518083038186803b158015612bf057600080fd5b505afa158015612c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c2891906158b5565b91506000306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c6557600080fd5b505afa158015612c79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9d9190615787565b6001600160a01b031663a609d912600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b158015612cf957600080fd5b505afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d319190615787565b6001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d6957600080fd5b505afa158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da191906158b5565b6008546040516370a0823160e01b81523060048201526001600160a01b038716906370a082319060240160206040518083038186803b158015612de357600080fd5b505afa158015612df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1b91906158b5565b612e259190615b08565b6040516001600160e01b031960e085901b16815260048101929092526024820152604481018b905260640160206040518083038186803b158015612e6857600080fd5b505afa158015612e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea091906158b5565b90508260086000828254612eb49190615b08565b92505081905550878560a001818151612ecd9190615b08565b9052506007546004805460408051630110f17360e51b8152905164e8d4a5100094936001600160a01b039093169263221e2e6092808201926020929091829003018186803b158015612f1e57600080fd5b505afa158015612f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f569190615787565b6001600160a01b0316637b80a5c08a6040518263ffffffff1660e01b8152600401612f8391815260200190565b604080518083038186803b158015612f9a57600080fd5b505afa158015612fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd29190615817565b51612fdd9190615ae9565b612fe79190615ac9565b6060860152600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b15801561302e57600080fd5b505afa158015613042573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130669190615787565b60a0860151606087015160808801516040516353ab9e7560e11b8152600481018c90526024810193909352604483019190915260648201526001600160a01b03919091169063a7573cea90608401600060405180830381600087803b1580156130ce57600080fd5b505af11580156130e2573d6000803e3d6000fd5b505050506131073384836130f69190615ab1565b6001600160a01b0385169190614fc3565b604080518981526020810183905290810184905260608101859052879033907fc37eb4d6b54bc2ffba48f4514cb217734c7ecd7c680cd2861e64ca48bc37a955906080016118ff565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561319c57600080fd5b505afa1580156131b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d491906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561321157600080fd5b505afa158015613225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132499190615899565b6132835760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b60058190556040518181527fd04894175d9fa4e8890c5d32ca8845426912f890c3d8ac5b5a561045892f899590602001610971565b6004805460408051630110f17360e51b8152905160009384936001600160a01b03169263221e2e609281830192602092829003018186803b1580156132fc57600080fd5b505afa158015613310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133349190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b15801561336c57600080fd5b505afa158015613380573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a491906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156133f457600080fd5b505afa158015613408573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342c9190615787565b6001600160a01b031663cd324209600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561348857600080fd5b505afa15801561349c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c09190615787565b6001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134f857600080fd5b505afa15801561350c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353091906158b5565b6040516001600160e01b031960e084901b168152600481019190915260248101849052670de0b6b3a7640000604482015260640160206040518083038186803b15801561357c57600080fd5b505afa158015613590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b491906158b5565b91505090565b600b546001600160a01b031633146136035760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b6044820152606401610692565b600c805460018082019092557fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038616179055600d8054918201815560009081527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb59091018390556009805484929061369e908490615ab1565b9091555050600e8054600181019091557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd015550600c546001600160a01b039091166000908152600f6020526040902055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561373d57600080fd5b505afa158015613751573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377591906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156137b257600080fd5b505afa1580156137c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137ea9190615899565b6138245760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b61382d81614ff3565b50565b60075460009015613867578164e8d4a51000600754856138509190615ae9565b61385a9190615ac9565b6138649190615b08565b90505b92915050565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b1580156138b957600080fd5b505afa1580156138cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561392e57600080fd5b505afa158015613942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139669190615899565b6139a05760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b600a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006139dd60025460ff1690565b15613a1d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b81600111158015613a2f575060d08211155b613aa15760405162461bcd60e51b815260206004820152603160248201527f426f6e64696e673a206475726174696f6e206d7573742062652062657477656560448201527f6e203120616e6420323038207765656b730000000000000000000000000000006064820152608401610692565b6004805460408051638fe6368360e01b815290516001600160a01b0390921692638fe63683928282019260209290829003018186803b158015613ae357600080fd5b505afa158015613af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1b9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613b5557600080fd5b505af1158015613b69573d6000803e3d6000fd5b50505050613b7561470a565b613bc9333085600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561133757600080fd5b6000600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b158015613c1957600080fd5b505afa158015613c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c519190615787565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b158015613ca557600080fd5b505afa158015613cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cdd91906158b5565b9050600060065484613cef9190615ae9565b613cf99043615ab1565b9050613d07338684846150b5565b9250600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015613d5757600080fd5b505afa158015613d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d8f9190615787565b604051630efe6a8b60e01b815233600482015260248101849052604481018590526001600160a01b039190911690630efe6a8b90606401600060405180830381600087803b158015613de057600080fd5b505af1158015613df4573d6000803e3d6000fd5b50506040805188815260208101869052908101879052606081018490528592503391507ff943cf10ef4d1e3239f4716ddecdf546e8ba8ab0e41deafd9a71a99936827e459060800160405180910390a3505092915050565b600b546001600160a01b03163314613e955760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b6044820152606401610692565b6010805460ff1916911515919091179055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b158015613ef457600080fd5b505afa158015613f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f2c91906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015613f6957600080fd5b505afa158015613f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fa19190615899565b613fdb5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b61382d8161527a565b6001600160a01b0383166140605760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a63616e742d73656e642d6475737460448201527f2d746f2d7a65726f2d61646472657373000000000000000000000000000000006064820152608401610692565b61406b60008361532f565b156140d05760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b6064820152608401610692565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415614131576040516001600160a01b0384169082156108fc029083906000818181858888f1935050505015801561412b573d6000803e3d6000fd5b50614145565b6141456001600160a01b0383168483614fc3565b604080516001600160a01b038086168252841660208201529081018290527f1e34c1aee8e83c2dcc14c21bb4bfeea7f46c0c998cb797ac7cc4d7a18f5c656b9060600160405180910390a1505050565b60025460ff166141e75760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610692565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61423961574d565b61427b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b1580156142bd57600080fd5b505afa1580156142d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142f59190615787565b604051627eeac760e11b8152336004820152602481018590526001600160a01b03919091169062fdd58e9060440160206040518083038186803b15801561433b57600080fd5b505afa15801561434f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061437391906158b5565b6001146143c25760405162461bcd60e51b815260206004820152601c60248201527f426f6e64696e673a2063616c6c6572206973206e6f74206f776e6572000000006044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561441257600080fd5b505afa158015614426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061444a9190615787565b604051636c7f3b2160e11b8152600481018690529091506001600160a01b0382169063d8fe76429060240160c06040518083038186803b15801561448d57600080fd5b505afa1580156144a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144c591906158cd565b9150816080015143116145405760405162461bcd60e51b815260206004820152602f60248201527f426f6e64696e673a2052656465656d206e6f7420616c6c6f776564206265666f60448201527f726520626f6e64696e672074696d6500000000000000000000000000000000006064820152608401610692565b6004805460408051638fe6368360e01b815290516001600160a01b0390921692638fe63683928282019260209290829003018186803b15801561458257600080fd5b505afa158015614596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ba9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156145f457600080fd5b505af1158015614608573d6000803e3d6000fd5b50506004805460408051630110f17360e51b815290516001600160a01b03909216945063221e2e6093508083019260209291829003018186803b15801561464e57600080fd5b505afa158015614662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146869190615787565b6001600160a01b0316637b80a5c0856040518263ffffffff1660e01b81526004016146b391815260200190565b604080518083038186803b1580156146ca57600080fd5b505afa1580156146de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147029190615817565b925050915091565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561475a57600080fd5b505afa15801561476e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147929190615787565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156147e457600080fd5b505afa1580156147f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061481c9190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561485d57600080fd5b505afa158015614871573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061489591906158b5565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156148e757600080fd5b505afa1580156148fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061491f9190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b15801561495757600080fd5b505afa15801561496b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061498f91906158b5565b9050600954836001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156149cd57600080fd5b505afa1580156149e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a0591906158b5565b614a0f9190615ab1565b8210158015614a1e5750600081115b15610808576000600954846001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015614a6157600080fd5b505afa158015614a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a9991906158b5565b614aa39190615ab1565b614aad9084615b08565b9050600854811115614af7578160085482614ac89190615b08565b614ad79064e8d4a51000615ae9565b614ae19190615ac9565b600754614aee9190615ab1565b60075560088190555b50505050565b6040516001600160a01b0380851660248301528316604482015260648101829052614af79085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152615351565b60025460ff1615614bc35760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586142143390565b6001600160a01b0383166000908152600f6020526040812054614c4e5760405162461bcd60e51b815260206004820152600e60248201526d6e6f74207631206164647265737360901b6044820152606401610692565b60008311614c9e5760405162461bcd60e51b815260206004820152601160248201527f4c5020616d6f756e74206973207a65726f0000000000000000000000000000006044820152606401610692565b81600111158015614cb0575060d08211155b614d225760405162461bcd60e51b815260206004820152602860248201527f4475726174696f6e206d757374206265206265747765656e203120616e64203260448201527f3038207765656b730000000000000000000000000000000000000000000000006064820152608401610692565b6001600160a01b038085166000908152600f602090815260408083208390556004805482516310a7bc4160e11b815292519495169363214f78829383830193909290829003018186803b158015614d7857600080fd5b505afa158015614d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614db09190615787565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b158015614e0457600080fd5b505afa158015614e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e3c91906158b5565b9050614e4661470a565b600060065484614e569190615ae9565b614e609043615ab1565b9050614e6e868684846150b5565b92508460096000828254614e829190615b08565b90915550506004805460408051630110f17360e51b815290516001600160a01b039092169263221e2e60928282019260209290829003018186803b158015614ec957600080fd5b505afa158015614edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f019190615787565b604051630efe6a8b60e01b81526001600160a01b03888116600483015260248201859052604482018690529190911690630efe6a8b90606401600060405180830381600087803b158015614f5457600080fd5b505af1158015614f68573d6000803e3d6000fd5b505060408051888152602081018690529081018790528592506001600160a01b03891691507fc8102fa5c0a66c20caa3ebb502aecfcc6e0ea963896d5a14c1bd8c10c456c5539060600160405180910390a350509392505050565b6040516001600160a01b03831660248201526044810182905261080890849063a9059cbb60e01b90606401614b31565b614ffe60008261532f565b6150705760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d6e6f742d7061727460448201527f2d6f662d7468652d70726f746f636f6c000000000000000000000000000000006064820152608401610692565b61507b600082615436565b506040516001600160a01b03821681527fddd12a8c3ce9bea5c97a5d25c8b777caab85752828f56b7b8ad5a0b30340a25f90602001610971565b6000806150c06132b8565b9050806151355760405162461bcd60e51b815260206004820152602760248201527f426f6e64696e673a2073686172652076616c75652073686f756c64206e6f742060448201527f6265206e756c6c000000000000000000000000000000000000000000000000006064820152608401610692565b600064e8d4a510006007548661514b9190615ae9565b6151559190615ac9565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156151a557600080fd5b505afa1580156151b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151dd9190615787565b604051632991fa3b60e21b81526001600160a01b038981166004830152602482018990526044820184905260648201879052919091169063a647e8ec90608401602060405180830381600087803b15801561523757600080fd5b505af115801561524b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061526f91906158b5565b979650505050505050565b61528560008261532f565b156152ea5760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b6064820152608401610692565b6152f560008261544b565b506040516001600160a01b03821681527fa3e4ba856dd0fdee3a33ab9b82499fd01f05236f3d08cc4e7108698c6e3e7e5090602001610971565b6001600160a01b03811660009081526001830160205260408120541515613864565b60006153a6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166154609092919063ffffffff16565b80519091501561080857808060200190518101906153c49190615899565b6108085760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610692565b6000613864836001600160a01b038416615479565b6000613864836001600160a01b038416615596565b606061546f84846000856155e5565b90505b9392505050565b6000818152600183016020526040812054801561558c57600061549d600183615b08565b85549091506000906154b190600190615b08565b90508181146155325760008660000182815481106154df57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061551057634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061555157634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050613867565b6000915050613867565b60008181526001830160205260408120546155dd57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155613867565b506000613867565b60608247101561565d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610692565b843b6156ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610692565b600080866001600160a01b031685876040516156c791906159c3565b60006040518083038185875af1925050503d8060008114615704576040519150601f19603f3d011682016040523d82523d6000602084013e615709565b606091505b509150915061526f82828660608315615723575081615472565b8251156157335782518084602001fd5b8160405162461bcd60e51b815260040161069291906159df565b60405180604001604052806002906020820280368337509192915050565b60006020828403121561577c578081fd5b813561547281615b9c565b600060208284031215615798578081fd5b815161547281615b9c565b6000806000606084860312156157b7578182fd5b83356157c281615b9c565b925060208401356157d281615b9c565b929592945050506040919091013590565b6000806000606084860312156157f7578283fd5b833561580281615b9c565b95602085013595506040909401359392505050565b600060408284031215615828578081fd5b82601f830112615836578081fd5b6158406040615a72565b808385604086011115615851578384fd5b835b6002811015615872578151845260209384019390910190600101615853565b509095945050505050565b60006020828403121561588e578081fd5b813561547281615bb1565b6000602082840312156158aa578081fd5b815161547281615bb1565b6000602082840312156158c6578081fd5b5051919050565b600060c082840312156158de578081fd5b6158e860c0615a72565b82516158f381615b9c565b808252506020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b600060208284031215615944578081fd5b5035919050565b6000806040838503121561595d578182fd5b50508035926020909101359150565b600080600060608486031215615980578283fd5b505081359360208301359350604090920135919050565b600081518084526159af816020860160208601615b1f565b601f01601f19169290920160200192915050565b600082516159d5818460208701615b1f565b9190910192915050565b6000602082526138646020830184615997565b6000610120820190506001600160a01b0385511682526020808601518184015260408601516040840152606086015160608401526080860151608084015260a086015160a084015260c083018560005b6002811015615a5f57815183529183019190830190600101615a42565b5050505082610100830152949350505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715615aa957634e487b7160e01b600052604160045260246000fd5b604052919050565b60008219821115615ac457615ac4615b86565b500190565b600082615ae457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615b0357615b03615b86565b500290565b600082821015615b1a57615b1a615b86565b500390565b60005b83811015615b3a578181015183820152602001615b22565b83811115614af75750506000910152565b600181811c90821680615b5f57607f821691505b60208210811415615b8057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461382d57600080fd5b801515811461382d57600080fdfea164736f6c6343000803000a0000000000000000000000004da97a8b831c345dbe6d16ff7432df2b7b776d98000000000000000000000000190474f062d05fba6d46a4d358c4d031075df2b400000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000009e0000000000000000000000000000000000000000000000000000000000000002400000000000000000000000089eae71b865a2a39cba62060ab1b40bbffae5b0d000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd000000000000000000000000a53a6fe2d8ad977ad926c485343ba39f32d3a3f60000000000000000000000007c76f4db70b7e2177de10de3e2f668dadcd111080000000000000000000000004007ce2083c7f3e18097aeb3a39bb8ec149a341d000000000000000000000000f6501068a54f3eab46c1f145cb9d3fb91658b22000000000000000000000000010693e86f2e7151b3010469e33b6c1c2da8887d6000000000000000000000000cefd0e73cc48b0b9d4c8683e52b7d7396600abb2000000000000000000000000d028babbdc15949aaa35587f95f9e96c7d49417d0000000000000000000000009968efe1424d802e1f79fd8af8da67b0f08c814d000000000000000000000000d3bc13258e685df436715104882888d087f87ed80000000000000000000000000709b103d46d71458a71e5d81230dd688809a53d000000000000000000000000e3e39161d35e9a81edec667a5387bfae857528540000000000000000000000007c361828849293684ddf7212fd1d2cb5f0aade700000000000000000000000009d3f4eeb533b8e3c8f50dbbd2e351d1bf2987908000000000000000000000000865dc9a621b50534ba3d17e0ea8447c315e31886000000000000000000000000324e0b53cefa84cf970833939249880f814557c6000000000000000000000000ce156d5d62a8f82326da8d808d0f3f76360036d000000000000000000000000026bdde6506bd32bd7b5cc5c73cd252807ff18568000000000000000000000000d6efc21d8c941aa06f90075de1588ac7e912fec6000000000000000000000000e0d62cc9233c7e2f1f23fe8c77d6b4d1a265d7cd0000000000000000000000000b54b916e90b8f28ad21da40638e0724132c9c93000000000000000000000000629cd43eaf443e66a9a69ed246728e1001289eac0000000000000000000000000709e442a5469b88bb090dd285b1b3a63fb0c22600000000000000000000000094a2ffdbdbd84984ac7967878c5c397126e7bbbe00000000000000000000000051ec66e63199176f59c80268e0be6ffa91fab2200000000000000000000000000a71e650f70b35fca8b70e71e4441df8d44e01e9000000000000000000000000c1b6052e707dff9017deab13ae9b89008fc1fc5d0000000000000000000000009be95ef84676393588e49ad8b99c9d4cdfdaa631000000000000000000000000fffff6e70842330948ca47254f2be673b1cb0db70000000000000000000000000000ce08fa224696a819877070bf378e8b131acf000000000000000000000000c2cb4b1bcaebaa78c8004e394cf90ba07a61c8f7000000000000000000000000b2812370f17465ae096ced55679428786734a6780000000000000000000000003eb851c3959f0d37e15c2d9476c4adb46d5231d1000000000000000000000000ad286cf287b91719ee85d3ba5cf3da483d631dba000000000000000000000000bd37a957773d883186b989f6b21c2094590222520000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000120e149b64c880000000000000000000000000000000000000000000000000bdbc41e0348b3000000000000000000000000000000000000000000000000001faebc1969c256d50a000000000000000000000000000000000000000000000097950c4685a7a837de0000000000000000000000000000000000000000000000fcc48cebda35139d542000000000000000000000000000000000000000000000086a657deffaa010000000000000000000000000000000000000000000000000065d7d85462acd3da8f0000000000000000000000000000000000000000000001e770370c4f2ea5d15f00000000000000000000000000000000000000000000003c3aee0b89d2b5def30000000000000000000000000000000000000000000000f1ba9428d88d218f070000000000000000000000000000000000000000000004999b2f3e9d028c000000000000000000000000000000000000000000000000082a1e88793a59061680000000000000000000000000000000000000000000000140e1e7ae7eba1b740b00000000000000000000000000000000000000000000005510e6a88fc67a95ac00000000000000000000000000000000000000000000022905914c52531970b800000000000000000000000000000000000000000000003043f2e885c284efa20000000000000000000000000000000000000000000001103208f6d5d335974500000000000000000000000000000000000000000000002940ff1c0c98440000000000000000000000000000000000000000000000000a69a2abeb1e9e5bd87d00000000000000000000000000000000000000000000054e3f87fb8377f4476400000000000000000000000000000000000000000000005579e670fe92a4623b0000000000000000000000000000000000000000000000c6a036eb4bc74000000000000000000000000000000000000000000000000000671e2f005f4a0cd2cf0000000000000000000000000000000000000000000007672c4b23049f1b1b800000000000000000000000000000000000000000000001fc7dbd2c5e27fddd7a000000000000000000000000000000000000000000000153bc08d918b19bf49e0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000000c862e9c7a8dc4a0f8200000000000000000000000000000000000000000000002824396cc4d140000000000000000000000000000000000000000000000000007ad7113237ab280000000000000000000000000000000000000000000000000050438f71849669261300000000000000000000000000000000000000000000053b1b7e838a88939a67000000000000000000000000000000000000000000000020cc0fc6929754000000000000000000000000000000000000000000000000005bdf9cb345eaf862e2000000000000000000000000000000000000000000000325664b203d8a84000000000000000000000000000000000000000000000000000168d28e3f00280000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000d0
Deployed Bytecode
0x60806040526004361061021d5760003560e01c80638f88f38d1161011d578063bf0d68e4116100b0578063dc0c00c41161007f578063f785f03d11610064578063f785f03d146105e0578063f941717d14610600578063fa3305c91461062d57610224565b8063dc0c00c4146105a0578063e2bbb158146105c057610224565b8063bf0d68e414610524578063c2ee3a0814610544578063c5d1cb6314610560578063cd6c212b1461058057610224565b8063a734f06e116100ec578063a734f06e146104b1578063aa1ec70a146104d9578063aadc68a5146104ef578063b167d4ea1461050457610224565b80638f88f38d146104465780638fd3ab801461045c5780639d7de6b314610471578063a194bcde1461049157610224565b8063481c6a75116101b057806365566d651161017f5780637cc6bd41116101645780637cc6bd41146103f15780637cd07e47146104115780638456cb591461043157610224565b806365566d65146103b957806373d4a13a146103cf57610224565b8063481c6a751461031f5780634956cf1c1461035757806352159150146103815780635c975abb146103a157610224565b80632f72589e116101ec5780632f72589e146102aa5780633b1ba367146102ca5780633f4ba83a146102ea578063422f1043146102ff57610224565b80630c76214114610229578063118c03ec1461025257806323cf3118146102685780632db8c1291461028a57610224565b3661022457005b600080fd5b34801561023557600080fd5b5061023f60085481565b6040519081526020015b60405180910390f35b34801561025e57600080fd5b5061023f60095481565b34801561027457600080fd5b5061028861028336600461576b565b61064d565b005b34801561029657600080fd5b506102886102a53660046157a3565b6106ca565b3480156102b657600080fd5b506102886102c5366004615933565b61080d565b3480156102d657600080fd5b506102886102e5366004615933565b61097c565b3480156102f657600080fd5b50610288611011565b34801561030b57600080fd5b5061028861031a36600461596c565b61114d565b34801561032b57600080fd5b5060045461033f906001600160a01b031681565b6040516001600160a01b039091168152602001610249565b34801561036357600080fd5b506010546103719060ff1681565b6040519015158152602001610249565b34801561038d57600080fd5b5061023f61039c366004615933565b611911565b3480156103ad57600080fd5b5060025460ff16610371565b3480156103c557600080fd5b5061023f60075481565b3480156103db57600080fd5b506103e4611eaf565b60405161024991906159df565b3480156103fd57600080fd5b5061028861040c366004615933565b611f3d565b34801561041d57600080fd5b50600b5461033f906001600160a01b031681565b34801561043d57600080fd5b5061028861256c565b34801561045257600080fd5b5061023f60055481565b34801561046857600080fd5b5061023f6126a6565b34801561047d57600080fd5b5061028861048c36600461594b565b612804565b34801561049d57600080fd5b506102886104ac366004615933565b613150565b3480156104bd57600080fd5b5061033f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b3480156104e557600080fd5b5061023f60065481565b3480156104fb57600080fd5b5061023f6132b8565b34801561051057600080fd5b5061028861051f3660046157e3565b6135ba565b34801561053057600080fd5b5061028861053f36600461576b565b6136f1565b34801561055057600080fd5b5061023f670de0b6b3a764000081565b34801561056c57600080fd5b5061023f61057b36600461594b565b613830565b34801561058c57600080fd5b50600a5461033f906001600160a01b031681565b3480156105ac57600080fd5b506102886105bb36600461576b565b61386d565b3480156105cc57600080fd5b5061023f6105db36600461594b565b6139cf565b3480156105ec57600080fd5b506102886105fb36600461587d565b613e4c565b34801561060c57600080fd5b5061023f61061b36600461576b565b600f6020526000908152604090205481565b34801561063957600080fd5b5061028861064836600461576b565b613ea8565b600b546001600160a01b0316331461069b5760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b60448201526064015b60405180910390fd5b600b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561071657600080fd5b505afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e91906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561078b57600080fd5b505afa15801561079f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c39190615899565b6107fd5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b610808838383613fe4565b505050565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561085957600080fd5b505afa15801561086d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156108ce57600080fd5b505afa1580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190615899565b6109405760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b60068190556040518181527f3a1c0b7d3cdecbab83b82697d51cbcdb308b3bbae63e597cbc958deb9c830e50906020015b60405180910390a150565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b1580156109c857600080fd5b505afa1580156109dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0091906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015610a3d57600080fd5b505afa158015610a51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a759190615899565b610aaf5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015610aff57600080fd5b505afa158015610b13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b379190615787565b604051630d2680e960e11b815260048101849052600060248201819052604482018190529192506001600160a01b03831690631a4d01d290606401602060405180830381600087803b158015610b8c57600080fd5b505af1158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc491906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b158015610c1457600080fd5b505afa158015610c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4c9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610c8657600080fd5b505af1158015610c9a573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610cee57600080fd5b505afa158015610d02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d269190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610d6757600080fd5b505afa158015610d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9f91906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e279190615787565b6001600160a01b031663a9059cbb600460009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e8357600080fd5b505afa158015610e97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebb9190615787565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b158015610f0357600080fd5b505af1158015610f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3b9190615899565b507f621af463096d58966fa48f497088db472e960b9f399d8cbf787ec0f7d2253365600460009054906101000a90046001600160a01b03166001600160a01b031663bc3ea0186040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b505afa158015610fbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe39190615787565b604080516001600160a01b03909216825260208201859052810183905260600160405180910390a150505050565b600480546040805163e63ab1e960e01b815290516001600160a01b03909216926391d1485492849263e63ab1e99281810192602092909190829003018186803b15801561105d57600080fd5b505afa158015611071573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109591906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156110d257600080fd5b505afa1580156110e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110a9190615899565b6111435760405162461bcd60e51b815260206004820152600a6024820152693737ba103830bab9b2b960b11b6044820152606401610692565b61114b614195565b565b60025460ff16156111935760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b60008061119f84614231565b815191935091506111ae61470a565b60006111be828460600151613830565b9050306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111f957600080fd5b505afa15801561120d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112319190615787565b6001600160a01b031663d5a8cf648486846040518463ffffffff1660e01b8152600401611260939291906159f2565b60206040518083038186803b15801561127857600080fd5b505afa15801561128c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b091906158b5565b9050808360a0018181516112c49190615ab1565b905250600880548291906000906112dc908490615b08565b92505081905550611380333089600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561133757600080fd5b505afa15801561134b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136f9190615787565b6001600160a01b0316929190614afd565b868360a0018181516113929190615ab1565b9052506004805460408051630110f17360e51b815290516001600160a01b039092169263221e2e60928282019260209290829003018186803b1580156113d757600080fd5b505afa1580156113eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140f9190615787565b604051635ae2fb3960e11b815233600482015260248101849052604481018890526001600160a01b03919091169063b5c5f67290606401600060405180830381600087803b15801561146057600080fd5b505af1158015611474573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c857600080fd5b505afa1580156114dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115009190615787565b60a085015160055460405163016cdd2960e61b815260048101929092526024820189905260448201526001600160a01b039190911690635b374a409060640160206040518083038186803b15801561155757600080fd5b505afa15801561156b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158f91906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156115df57600080fd5b505afa1580156115f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116179190615787565b604051630efe6a8b60e01b815233600482015260248101839052604481018990526001600160a01b039190911690630efe6a8b90606401600060405180830381600087803b15801561166857600080fd5b505af115801561167c573d6000803e3d6000fd5b505050506006548661168e9190615ae9565b6116989043615ab1565b60808501526116a561470a565b64e8d4a51000600754600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156116fc57600080fd5b505afa158015611710573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117349190615787565b6001600160a01b0316637b80a5c08a6040518263ffffffff1660e01b815260040161176191815260200190565b604080518083038186803b15801561177857600080fd5b505afa15801561178c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b09190615817565b516117bb9190615ae9565b6117c59190615ac9565b6060850152600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b15801561180c57600080fd5b505afa158015611820573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118449190615787565b60a0850151606086015160808701516040516353ab9e7560e11b8152600481018c90526024810193909352604483019190915260648201526001600160a01b03919091169063a7573cea90608401600060405180830381600087803b1580156118ac57600080fd5b505af11580156118c0573d6000803e3d6000fd5b50505060a0850151604080519182526020820184905289925033917f4419681a20e94d59aaa91e563559dc52e7fb9ec1540b072ce92014f31961ce0091015b60405180910390a35050505050505050565b600480546040805163310c7a0f60e21b8152905160009384936001600160a01b03169263c431e83c9281830192602092829003018186803b15801561195557600080fd5b505afa158015611969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198d9190615787565b604051636c7f3b2160e11b8152600481018590529091506000906001600160a01b0383169063d8fe76429060240160c06040518083038186803b1580156119d357600080fd5b505afa1580156119e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0b91906158cd565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5d57600080fd5b505afa158015611a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a959190615787565b6001600160a01b0316637b80a5c0866040518263ffffffff1660e01b8152600401611ac291815260200190565b604080518083038186803b158015611ad957600080fd5b505afa158015611aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b119190615817565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b6357600080fd5b505afa158015611b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9b9190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015611bdc57600080fd5b505afa158015611bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1491906158b5565b9050600954846001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c5257600080fd5b505afa158015611c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8a91906158b5565b611c949190615ab1565b8110611ea1576000600954856001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cd857600080fd5b505afa158015611cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1091906158b5565b611d1a9190615ab1565b611d249083615b08565b60075460085491925090821115611e6757600060085483611d459190615b08565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015611d9557600080fd5b505afa158015611da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcd9190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b158015611e0557600080fd5b505afa158015611e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3d91906158b5565b611e4c8264e8d4a51000615ae9565b611e569190615ac9565b600754611e639190615ab1565b9150505b6060850151845164e8d4a5100090611e80908490615ae9565b611e8a9190615ac9565b611e949190615b08565b9650505050505050611eaa565b60009450505050505b919050565b60038054611ebc90615b4b565b80601f0160208091040260200160405190810160405280929190818152602001828054611ee890615b4b565b8015611f355780601f10611f0a57610100808354040283529160200191611f35565b820191906000526020600020905b815481529060010190602001808311611f1857829003601f168201915b505050505081565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b158015611f8957600080fd5b505afa158015611f9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015611ffe57600080fd5b505afa158015612012573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120369190615899565b6120705760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156120c057600080fd5b505afa1580156120d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f89190615787565b604051630d2680e960e11b815260048101849052600160248201526000604482018190529192506001600160a01b03831690631a4d01d290606401602060405180830381600087803b15801561214d57600080fd5b505af1158015612161573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218591906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b0316638fe636836040518163ffffffff1660e01b815260040160206040518083038186803b1580156121d557600080fd5b505afa1580156121e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220d9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561224757600080fd5b505af115801561225b573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156122af57600080fd5b505afa1580156122c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e79190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561232857600080fd5b505afa15801561233c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236091906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b1580156123b057600080fd5b505afa1580156123c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e89190615787565b6001600160a01b031663a9059cbb600460009054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b815260040160206040518083038186803b15801561244457600080fd5b505afa158015612458573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247c9190615787565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b1580156124c457600080fd5b505af11580156124d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fc9190615899565b507f621af463096d58966fa48f497088db472e960b9f399d8cbf787ec0f7d2253365600460009054906101000a90046001600160a01b03166001600160a01b031663017df3276040518163ffffffff1660e01b815260040160206040518083038186803b158015610fab57600080fd5b600480546040805163e63ab1e960e01b815290516001600160a01b03909216926391d1485492849263e63ab1e99281810192602092909190829003018186803b1580156125b857600080fd5b505afa1580156125cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f091906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561262d57600080fd5b505afa158015612641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126659190615899565b61269e5760405162461bcd60e51b815260206004820152600a6024820152693737ba103830bab9b2b960b11b6044820152606401610692565b61114b614b7d565b60105460009060ff166126fb5760405162461bcd60e51b815260206004820152601060248201527f6e6f7420696e206d6967726174696f6e000000000000000000000000000000006044820152606401610692565b50336000908152600f60205260409020548061274a5760405162461bcd60e51b815260206004820152600e60248201526d6e6f74207631206164647265737360901b6044820152606401610692565b612800600c61275a600184615b08565b8154811061277857634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316600d61279a600185615b08565b815481106127b857634e487b7160e01b600052603260045260246000fd5b9060005260206000200154600e6001856127d29190615b08565b815481106127f057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154614bf8565b5090565b60025460ff161561284a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b60008061285683614231565b91509150838160a0015110156128ae5760405162461bcd60e51b815260206004820152601760248201527f426f6e64696e673a20616d6f756e7420746f6f206269670000000000000000006044820152606401610692565b6000306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156128e957600080fd5b505afa1580156128fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129219190615787565b6001600160a01b031663629056cb8385886040518463ffffffff1660e01b8152600401612950939291906159f2565b60206040518083038186803b15801561296857600080fd5b505afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129a091906158b5565b90506129aa61470a565b825160608301516000916129bd91613830565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015612a0d57600080fd5b505afa158015612a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a459190615787565b604051635ae2fb3960e11b815233600482015260248101849052604481018790526001600160a01b03919091169063b5c5f67290606401600060405180830381600087803b158015612a9657600080fd5b505af1158015612aaa573d6000803e3d6000fd5b505050506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b158015612afe57600080fd5b505afa158015612b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b369190615787565b9050306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612b7157600080fd5b505afa158015612b85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba99190615787565b6001600160a01b031663a64154f08587856040518463ffffffff1660e01b8152600401612bd8939291906159f2565b60206040518083038186803b158015612bf057600080fd5b505afa158015612c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c2891906158b5565b91506000306001600160a01b031663cd6c212b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c6557600080fd5b505afa158015612c79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9d9190615787565b6001600160a01b031663a609d912600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b158015612cf957600080fd5b505afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d319190615787565b6001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d6957600080fd5b505afa158015612d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da191906158b5565b6008546040516370a0823160e01b81523060048201526001600160a01b038716906370a082319060240160206040518083038186803b158015612de357600080fd5b505afa158015612df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1b91906158b5565b612e259190615b08565b6040516001600160e01b031960e085901b16815260048101929092526024820152604481018b905260640160206040518083038186803b158015612e6857600080fd5b505afa158015612e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea091906158b5565b90508260086000828254612eb49190615b08565b92505081905550878560a001818151612ecd9190615b08565b9052506007546004805460408051630110f17360e51b8152905164e8d4a5100094936001600160a01b039093169263221e2e6092808201926020929091829003018186803b158015612f1e57600080fd5b505afa158015612f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f569190615787565b6001600160a01b0316637b80a5c08a6040518263ffffffff1660e01b8152600401612f8391815260200190565b604080518083038186803b158015612f9a57600080fd5b505afa158015612fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd29190615817565b51612fdd9190615ae9565b612fe79190615ac9565b6060860152600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b15801561302e57600080fd5b505afa158015613042573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130669190615787565b60a0860151606087015160808801516040516353ab9e7560e11b8152600481018c90526024810193909352604483019190915260648201526001600160a01b03919091169063a7573cea90608401600060405180830381600087803b1580156130ce57600080fd5b505af11580156130e2573d6000803e3d6000fd5b505050506131073384836130f69190615ab1565b6001600160a01b0385169190614fc3565b604080518981526020810183905290810184905260608101859052879033907fc37eb4d6b54bc2ffba48f4514cb217734c7ecd7c680cd2861e64ca48bc37a955906080016118ff565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561319c57600080fd5b505afa1580156131b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d491906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561321157600080fd5b505afa158015613225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132499190615899565b6132835760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b60058190556040518181527fd04894175d9fa4e8890c5d32ca8845426912f890c3d8ac5b5a561045892f899590602001610971565b6004805460408051630110f17360e51b8152905160009384936001600160a01b03169263221e2e609281830192602092829003018186803b1580156132fc57600080fd5b505afa158015613310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133349190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b15801561336c57600080fd5b505afa158015613380573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a491906158b5565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b1580156133f457600080fd5b505afa158015613408573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342c9190615787565b6001600160a01b031663cd324209600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561348857600080fd5b505afa15801561349c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c09190615787565b6001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156134f857600080fd5b505afa15801561350c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353091906158b5565b6040516001600160e01b031960e084901b168152600481019190915260248101849052670de0b6b3a7640000604482015260640160206040518083038186803b15801561357c57600080fd5b505afa158015613590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b491906158b5565b91505090565b600b546001600160a01b031633146136035760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b6044820152606401610692565b600c805460018082019092557fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038616179055600d8054918201815560009081527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb59091018390556009805484929061369e908490615ab1565b9091555050600e8054600181019091557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd015550600c546001600160a01b039091166000908152600f6020526040902055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b15801561373d57600080fd5b505afa158015613751573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377591906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b1580156137b257600080fd5b505afa1580156137c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137ea9190615899565b6138245760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b61382d81614ff3565b50565b60075460009015613867578164e8d4a51000600754856138509190615ae9565b61385a9190615ac9565b6138649190615b08565b90505b92915050565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b1580156138b957600080fd5b505afa1580156138cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f191906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561392e57600080fd5b505afa158015613942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139669190615899565b6139a05760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b600a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006139dd60025460ff1690565b15613a1d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b81600111158015613a2f575060d08211155b613aa15760405162461bcd60e51b815260206004820152603160248201527f426f6e64696e673a206475726174696f6e206d7573742062652062657477656560448201527f6e203120616e6420323038207765656b730000000000000000000000000000006064820152608401610692565b6004805460408051638fe6368360e01b815290516001600160a01b0390921692638fe63683928282019260209290829003018186803b158015613ae357600080fd5b505afa158015613af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b1b9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613b5557600080fd5b505af1158015613b69573d6000803e3d6000fd5b50505050613b7561470a565b613bc9333085600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b15801561133757600080fd5b6000600460009054906101000a90046001600160a01b03166001600160a01b031663214f78826040518163ffffffff1660e01b815260040160206040518083038186803b158015613c1957600080fd5b505afa158015613c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c519190615787565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b158015613ca557600080fd5b505afa158015613cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cdd91906158b5565b9050600060065484613cef9190615ae9565b613cf99043615ab1565b9050613d07338684846150b5565b9250600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b158015613d5757600080fd5b505afa158015613d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d8f9190615787565b604051630efe6a8b60e01b815233600482015260248101849052604481018590526001600160a01b039190911690630efe6a8b90606401600060405180830381600087803b158015613de057600080fd5b505af1158015613df4573d6000803e3d6000fd5b50506040805188815260208101869052908101879052606081018490528592503391507ff943cf10ef4d1e3239f4716ddecdf546e8ba8ab0e41deafd9a71a99936827e459060800160405180910390a3505092915050565b600b546001600160a01b03163314613e955760405162461bcd60e51b815260206004820152600c60248201526b3737ba1036b4b3b930ba37b960a11b6044820152606401610692565b6010805460ff1916911515919091179055565b600480546040805163039b1cd560e61b815290516001600160a01b03909216926391d1485492849263e6c735409281810192602092909190829003018186803b158015613ef457600080fd5b505afa158015613f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f2c91906158b5565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b158015613f6957600080fd5b505afa158015613f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fa19190615899565b613fdb5760405162461bcd60e51b815260206004820152600b60248201526a3737ba1036b0b730b3b2b960a91b6044820152606401610692565b61382d8161527a565b6001600160a01b0383166140605760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a63616e742d73656e642d6475737460448201527f2d746f2d7a65726f2d61646472657373000000000000000000000000000000006064820152608401610692565b61406b60008361532f565b156140d05760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b6064820152608401610692565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415614131576040516001600160a01b0384169082156108fc029083906000818181858888f1935050505015801561412b573d6000803e3d6000fd5b50614145565b6141456001600160a01b0383168483614fc3565b604080516001600160a01b038086168252841660208201529081018290527f1e34c1aee8e83c2dcc14c21bb4bfeea7f46c0c998cb797ac7cc4d7a18f5c656b9060600160405180910390a1505050565b60025460ff166141e75760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610692565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61423961574d565b61427b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b600480546040805163310c7a0f60e21b815290516001600160a01b039092169263c431e83c928282019260209290829003018186803b1580156142bd57600080fd5b505afa1580156142d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142f59190615787565b604051627eeac760e11b8152336004820152602481018590526001600160a01b03919091169062fdd58e9060440160206040518083038186803b15801561433b57600080fd5b505afa15801561434f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061437391906158b5565b6001146143c25760405162461bcd60e51b815260206004820152601c60248201527f426f6e64696e673a2063616c6c6572206973206e6f74206f776e6572000000006044820152606401610692565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561441257600080fd5b505afa158015614426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061444a9190615787565b604051636c7f3b2160e11b8152600481018690529091506001600160a01b0382169063d8fe76429060240160c06040518083038186803b15801561448d57600080fd5b505afa1580156144a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144c591906158cd565b9150816080015143116145405760405162461bcd60e51b815260206004820152602f60248201527f426f6e64696e673a2052656465656d206e6f7420616c6c6f776564206265666f60448201527f726520626f6e64696e672074696d6500000000000000000000000000000000006064820152608401610692565b6004805460408051638fe6368360e01b815290516001600160a01b0390921692638fe63683928282019260209290829003018186803b15801561458257600080fd5b505afa158015614596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ba9190615787565b6001600160a01b031663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156145f457600080fd5b505af1158015614608573d6000803e3d6000fd5b50506004805460408051630110f17360e51b815290516001600160a01b03909216945063221e2e6093508083019260209291829003018186803b15801561464e57600080fd5b505afa158015614662573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146869190615787565b6001600160a01b0316637b80a5c0856040518263ffffffff1660e01b81526004016146b391815260200190565b604080518083038186803b1580156146ca57600080fd5b505afa1580156146de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147029190615817565b925050915091565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561475a57600080fd5b505afa15801561476e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147929190615787565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663d3815fb96040518163ffffffff1660e01b815260040160206040518083038186803b1580156147e457600080fd5b505afa1580156147f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061481c9190615787565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b15801561485d57600080fd5b505afa158015614871573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061489591906158b5565b90506000600460009054906101000a90046001600160a01b03166001600160a01b031663221e2e606040518163ffffffff1660e01b815260040160206040518083038186803b1580156148e757600080fd5b505afa1580156148fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061491f9190615787565b6001600160a01b0316633a98ef396040518163ffffffff1660e01b815260040160206040518083038186803b15801561495757600080fd5b505afa15801561496b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061498f91906158b5565b9050600954836001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156149cd57600080fd5b505afa1580156149e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a0591906158b5565b614a0f9190615ab1565b8210158015614a1e5750600081115b15610808576000600954846001600160a01b031663132c4feb6040518163ffffffff1660e01b815260040160206040518083038186803b158015614a6157600080fd5b505afa158015614a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a9991906158b5565b614aa39190615ab1565b614aad9084615b08565b9050600854811115614af7578160085482614ac89190615b08565b614ad79064e8d4a51000615ae9565b614ae19190615ac9565b600754614aee9190615ab1565b60075560088190555b50505050565b6040516001600160a01b0380851660248301528316604482015260648101829052614af79085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152615351565b60025460ff1615614bc35760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610692565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586142143390565b6001600160a01b0383166000908152600f6020526040812054614c4e5760405162461bcd60e51b815260206004820152600e60248201526d6e6f74207631206164647265737360901b6044820152606401610692565b60008311614c9e5760405162461bcd60e51b815260206004820152601160248201527f4c5020616d6f756e74206973207a65726f0000000000000000000000000000006044820152606401610692565b81600111158015614cb0575060d08211155b614d225760405162461bcd60e51b815260206004820152602860248201527f4475726174696f6e206d757374206265206265747765656e203120616e64203260448201527f3038207765656b730000000000000000000000000000000000000000000000006064820152608401610692565b6001600160a01b038085166000908152600f602090815260408083208390556004805482516310a7bc4160e11b815292519495169363214f78829383830193909290829003018186803b158015614d7857600080fd5b505afa158015614d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614db09190615787565b60055460405163016cdd2960e61b8152600481018790526024810186905260448101919091526001600160a01b039190911690635b374a409060640160206040518083038186803b158015614e0457600080fd5b505afa158015614e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e3c91906158b5565b9050614e4661470a565b600060065484614e569190615ae9565b614e609043615ab1565b9050614e6e868684846150b5565b92508460096000828254614e829190615b08565b90915550506004805460408051630110f17360e51b815290516001600160a01b039092169263221e2e60928282019260209290829003018186803b158015614ec957600080fd5b505afa158015614edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f019190615787565b604051630efe6a8b60e01b81526001600160a01b03888116600483015260248201859052604482018690529190911690630efe6a8b90606401600060405180830381600087803b158015614f5457600080fd5b505af1158015614f68573d6000803e3d6000fd5b505060408051888152602081018690529081018790528592506001600160a01b03891691507fc8102fa5c0a66c20caa3ebb502aecfcc6e0ea963896d5a14c1bd8c10c456c5539060600160405180910390a350509392505050565b6040516001600160a01b03831660248201526044810182905261080890849063a9059cbb60e01b90606401614b31565b614ffe60008261532f565b6150705760405162461bcd60e51b815260206004820152603060248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d6e6f742d7061727460448201527f2d6f662d7468652d70726f746f636f6c000000000000000000000000000000006064820152608401610692565b61507b600082615436565b506040516001600160a01b03821681527fddd12a8c3ce9bea5c97a5d25c8b777caab85752828f56b7b8ad5a0b30340a25f90602001610971565b6000806150c06132b8565b9050806151355760405162461bcd60e51b815260206004820152602760248201527f426f6e64696e673a2073686172652076616c75652073686f756c64206e6f742060448201527f6265206e756c6c000000000000000000000000000000000000000000000000006064820152608401610692565b600064e8d4a510006007548661514b9190615ae9565b6151559190615ac9565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663c431e83c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156151a557600080fd5b505afa1580156151b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151dd9190615787565b604051632991fa3b60e21b81526001600160a01b038981166004830152602482018990526044820184905260648201879052919091169063a647e8ec90608401602060405180830381600087803b15801561523757600080fd5b505af115801561524b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061526f91906158b5565b979650505050505050565b61528560008261532f565b156152ea5760405162461bcd60e51b815260206004820152602f60248201527f636f6c6c65637461626c652d647573743a3a746f6b656e2d69732d706172742d60448201526e1bd98b5d1a194b5c1c9bdd1bd8dbdb608a1b6064820152608401610692565b6152f560008261544b565b506040516001600160a01b03821681527fa3e4ba856dd0fdee3a33ab9b82499fd01f05236f3d08cc4e7108698c6e3e7e5090602001610971565b6001600160a01b03811660009081526001830160205260408120541515613864565b60006153a6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166154609092919063ffffffff16565b80519091501561080857808060200190518101906153c49190615899565b6108085760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610692565b6000613864836001600160a01b038416615479565b6000613864836001600160a01b038416615596565b606061546f84846000856155e5565b90505b9392505050565b6000818152600183016020526040812054801561558c57600061549d600183615b08565b85549091506000906154b190600190615b08565b90508181146155325760008660000182815481106154df57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061551057634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061555157634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050613867565b6000915050613867565b60008181526001830160205260408120546155dd57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155613867565b506000613867565b60608247101561565d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610692565b843b6156ab5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610692565b600080866001600160a01b031685876040516156c791906159c3565b60006040518083038185875af1925050503d8060008114615704576040519150601f19603f3d011682016040523d82523d6000602084013e615709565b606091505b509150915061526f82828660608315615723575081615472565b8251156157335782518084602001fd5b8160405162461bcd60e51b815260040161069291906159df565b60405180604001604052806002906020820280368337509192915050565b60006020828403121561577c578081fd5b813561547281615b9c565b600060208284031215615798578081fd5b815161547281615b9c565b6000806000606084860312156157b7578182fd5b83356157c281615b9c565b925060208401356157d281615b9c565b929592945050506040919091013590565b6000806000606084860312156157f7578283fd5b833561580281615b9c565b95602085013595506040909401359392505050565b600060408284031215615828578081fd5b82601f830112615836578081fd5b6158406040615a72565b808385604086011115615851578384fd5b835b6002811015615872578151845260209384019390910190600101615853565b509095945050505050565b60006020828403121561588e578081fd5b813561547281615bb1565b6000602082840312156158aa578081fd5b815161547281615bb1565b6000602082840312156158c6578081fd5b5051919050565b600060c082840312156158de578081fd5b6158e860c0615a72565b82516158f381615b9c565b808252506020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b600060208284031215615944578081fd5b5035919050565b6000806040838503121561595d578182fd5b50508035926020909101359150565b600080600060608486031215615980578283fd5b505081359360208301359350604090920135919050565b600081518084526159af816020860160208601615b1f565b601f01601f19169290920160200192915050565b600082516159d5818460208701615b1f565b9190910192915050565b6000602082526138646020830184615997565b6000610120820190506001600160a01b0385511682526020808601518184015260408601516040840152606086015160608401526080860151608084015260a086015160a084015260c083018560005b6002811015615a5f57815183529183019190830190600101615a42565b5050505082610100830152949350505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715615aa957634e487b7160e01b600052604160045260246000fd5b604052919050565b60008219821115615ac457615ac4615b86565b500190565b600082615ae457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615b0357615b03615b86565b500290565b600082821015615b1a57615b1a615b86565b500390565b60005b83811015615b3a578181015183820152602001615b22565b83811115614af75750506000910152565b600181811c90821680615b5f57607f821691505b60208210811415615b8057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461382d57600080fd5b801515811461382d57600080fdfea164736f6c6343000803000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004da97a8b831c345dbe6d16ff7432df2b7b776d98000000000000000000000000190474f062d05fba6d46a4d358c4d031075df2b400000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000009e0000000000000000000000000000000000000000000000000000000000000002400000000000000000000000089eae71b865a2a39cba62060ab1b40bbffae5b0d000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd000000000000000000000000a53a6fe2d8ad977ad926c485343ba39f32d3a3f60000000000000000000000007c76f4db70b7e2177de10de3e2f668dadcd111080000000000000000000000004007ce2083c7f3e18097aeb3a39bb8ec149a341d000000000000000000000000f6501068a54f3eab46c1f145cb9d3fb91658b22000000000000000000000000010693e86f2e7151b3010469e33b6c1c2da8887d6000000000000000000000000cefd0e73cc48b0b9d4c8683e52b7d7396600abb2000000000000000000000000d028babbdc15949aaa35587f95f9e96c7d49417d0000000000000000000000009968efe1424d802e1f79fd8af8da67b0f08c814d000000000000000000000000d3bc13258e685df436715104882888d087f87ed80000000000000000000000000709b103d46d71458a71e5d81230dd688809a53d000000000000000000000000e3e39161d35e9a81edec667a5387bfae857528540000000000000000000000007c361828849293684ddf7212fd1d2cb5f0aade700000000000000000000000009d3f4eeb533b8e3c8f50dbbd2e351d1bf2987908000000000000000000000000865dc9a621b50534ba3d17e0ea8447c315e31886000000000000000000000000324e0b53cefa84cf970833939249880f814557c6000000000000000000000000ce156d5d62a8f82326da8d808d0f3f76360036d000000000000000000000000026bdde6506bd32bd7b5cc5c73cd252807ff18568000000000000000000000000d6efc21d8c941aa06f90075de1588ac7e912fec6000000000000000000000000e0d62cc9233c7e2f1f23fe8c77d6b4d1a265d7cd0000000000000000000000000b54b916e90b8f28ad21da40638e0724132c9c93000000000000000000000000629cd43eaf443e66a9a69ed246728e1001289eac0000000000000000000000000709e442a5469b88bb090dd285b1b3a63fb0c22600000000000000000000000094a2ffdbdbd84984ac7967878c5c397126e7bbbe00000000000000000000000051ec66e63199176f59c80268e0be6ffa91fab2200000000000000000000000000a71e650f70b35fca8b70e71e4441df8d44e01e9000000000000000000000000c1b6052e707dff9017deab13ae9b89008fc1fc5d0000000000000000000000009be95ef84676393588e49ad8b99c9d4cdfdaa631000000000000000000000000fffff6e70842330948ca47254f2be673b1cb0db70000000000000000000000000000ce08fa224696a819877070bf378e8b131acf000000000000000000000000c2cb4b1bcaebaa78c8004e394cf90ba07a61c8f7000000000000000000000000b2812370f17465ae096ced55679428786734a6780000000000000000000000003eb851c3959f0d37e15c2d9476c4adb46d5231d1000000000000000000000000ad286cf287b91719ee85d3ba5cf3da483d631dba000000000000000000000000bd37a957773d883186b989f6b21c2094590222520000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000120e149b64c880000000000000000000000000000000000000000000000000bdbc41e0348b3000000000000000000000000000000000000000000000000001faebc1969c256d50a000000000000000000000000000000000000000000000097950c4685a7a837de0000000000000000000000000000000000000000000000fcc48cebda35139d542000000000000000000000000000000000000000000000086a657deffaa010000000000000000000000000000000000000000000000000065d7d85462acd3da8f0000000000000000000000000000000000000000000001e770370c4f2ea5d15f00000000000000000000000000000000000000000000003c3aee0b89d2b5def30000000000000000000000000000000000000000000000f1ba9428d88d218f070000000000000000000000000000000000000000000004999b2f3e9d028c000000000000000000000000000000000000000000000000082a1e88793a59061680000000000000000000000000000000000000000000000140e1e7ae7eba1b740b00000000000000000000000000000000000000000000005510e6a88fc67a95ac00000000000000000000000000000000000000000000022905914c52531970b800000000000000000000000000000000000000000000003043f2e885c284efa20000000000000000000000000000000000000000000001103208f6d5d335974500000000000000000000000000000000000000000000002940ff1c0c98440000000000000000000000000000000000000000000000000a69a2abeb1e9e5bd87d00000000000000000000000000000000000000000000054e3f87fb8377f4476400000000000000000000000000000000000000000000005579e670fe92a4623b0000000000000000000000000000000000000000000000c6a036eb4bc74000000000000000000000000000000000000000000000000000671e2f005f4a0cd2cf0000000000000000000000000000000000000000000007672c4b23049f1b1b800000000000000000000000000000000000000000000001fc7dbd2c5e27fddd7a000000000000000000000000000000000000000000000153bc08d918b19bf49e0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000000c862e9c7a8dc4a0f8200000000000000000000000000000000000000000000002824396cc4d140000000000000000000000000000000000000000000000000007ad7113237ab280000000000000000000000000000000000000000000000000050438f71849669261300000000000000000000000000000000000000000000053b1b7e838a88939a67000000000000000000000000000000000000000000000020cc0fc6929754000000000000000000000000000000000000000000000000005bdf9cb345eaf862e2000000000000000000000000000000000000000000000325664b203d8a84000000000000000000000000000000000000000000000000000168d28e3f00280000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000d0
-----Decoded View---------------
Arg [0] : _manager (address): 0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98
Arg [1] : _bondingFormulasAddress (address): 0x190474f062D05fba6d46A4D358C4d031075DF2b4
Arg [2] : _originals (address[]): 0x89eae71B865A2A39cBa62060aB1b40bbFFaE5b0D,0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd,0xa53A6fE2d8Ad977aD926C485343Ba39f32D3A3F6,0x7c76f4DB70b7E2177de10DE3e2f668daDcd11108,0x4007CE2083c7F3E18097aeB3A39bb8eC149a341d,0xf6501068a54f3EAb46C1F145CB9d3fb91658B220,0x10693e86f2e7151B3010469E33b6C1C2dA8887d6,0xCEFD0E73cC48B0b9d4C8683E52B7d7396600AbB2,0xD028BaBBdC15949aAA35587f95F9E96c7d49417D,0x9968eFe1424D802e1f79FD8aF8dA67b0f08C814d,0xd3BC13258e685df436715104882888d087f87ED8,0x0709B103d46d71458a71e5d81230DD688809A53D,0xE3E39161d35E9A81edEc667a5387bfAE85752854,0x7c361828849293684DdF7212Fd1d2Cb5f0aADe70,0x9d3F4EEB533B8e3C8f50dbbD2E351D1BF2987908,0x865Dc9A621B50534BA3d17e0Ea8447C315E31886,0x324E0b53CefA84CF970833939249880f814557c6,0xcE156D5d62a8F82326dA8d808D0f3F76360036D0,0x26bdDe6506bd32bD7B5Cc5C73cd252807fF18568,0xD6EfC21d8c941AA06F90075dE1588ac7E912Fec6,0xe0D62CC9233C7E2F1f23fE8C77D6b4D1a265D7Cd,0x0B54B916E90b8f28ad21dA40638E0724132C9c93,0x629cd43eAF443e66A9a69ED246728E1001289EAC,0x0709e442A5469B88bB090dD285b1B3a63fb0c226,0x94A2fFDbDbD84984AC7967878C5C397126E7BBBe,0x51EC66e63199176f59C80268e0Be6fFa91Fab220,0x0a71e650F70B35fca8b70e71E4441df8D44E01e9,0xC1b6052E707dfF9017DEAb13ae9B89008FC1Fc5d,0x9be95ef84676393588e49Ad8B99c9d4CdFdAA631,0xFFFFF6E70842330948Ca47254F2bE673B1cb0dB7,0x0000CE08fa224696A819877070BF378e8B131ACF,0xC2cb4B1bCAEbAa78c8004e394CF90BA07A61C8f7,0xB2812370f17465AE096Ced55679428786734a678,0x3eb851c3959F0d37E15C2d9476C4ADb46d5231D1,0xad286cF287b91719eE85d3ba5cF3DA483D631Dba,0xbD37A957773D883186B989f6b21c209459022252
Arg [3] : _lpBalances (uint256[]): 1301000000000000000,3500000000000000000000,9351040526163838324896,44739174270101943975392,74603879373206500005186,2483850000000000000000,1878674425540571814543,8991650309086743220575,1111050988607803612915,4459109737462155546375,21723000000000000000000,38555895255762442000000,5919236274824521937931,1569191092350025897388,10201450658519659933880,890339946944155414434,5021119790948940093253,761000000000000000000,49172294677407855270013,25055256356185888278372,1576757078627228869179,3664000000000000000000,1902189597146391302863,34959771702943278635904,9380006436252701023610,6266995559166564365470,100000000000000000000,3696476262155265118082,740480000000000000000,2266000000000000000000,1480607760433248019987,24702171480214199310951,605000000000000000000,1694766661387270251234,14857000000000000000000,26000000000000000000
Arg [4] : _weeks (uint256[]): 176,30,208,208,208,32,208,208,4,1,67,208,208,109,12,29,1,1,3,4,7,1,128,2,4,3,208,6,1,208,2,1,12,208,4,208
-----Encoded View---------------
116 Constructor Arguments found :
Arg [0] : 0000000000000000000000004da97a8b831c345dbe6d16ff7432df2b7b776d98
Arg [1] : 000000000000000000000000190474f062d05fba6d46a4d358c4d031075df2b4
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000540
Arg [4] : 00000000000000000000000000000000000000000000000000000000000009e0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [6] : 00000000000000000000000089eae71b865a2a39cba62060ab1b40bbffae5b0d
Arg [7] : 000000000000000000000000efc0e701a824943b469a694ac564aa1eff7ab7dd
Arg [8] : 000000000000000000000000a53a6fe2d8ad977ad926c485343ba39f32d3a3f6
Arg [9] : 0000000000000000000000007c76f4db70b7e2177de10de3e2f668dadcd11108
Arg [10] : 0000000000000000000000004007ce2083c7f3e18097aeb3a39bb8ec149a341d
Arg [11] : 000000000000000000000000f6501068a54f3eab46c1f145cb9d3fb91658b220
Arg [12] : 00000000000000000000000010693e86f2e7151b3010469e33b6c1c2da8887d6
Arg [13] : 000000000000000000000000cefd0e73cc48b0b9d4c8683e52b7d7396600abb2
Arg [14] : 000000000000000000000000d028babbdc15949aaa35587f95f9e96c7d49417d
Arg [15] : 0000000000000000000000009968efe1424d802e1f79fd8af8da67b0f08c814d
Arg [16] : 000000000000000000000000d3bc13258e685df436715104882888d087f87ed8
Arg [17] : 0000000000000000000000000709b103d46d71458a71e5d81230dd688809a53d
Arg [18] : 000000000000000000000000e3e39161d35e9a81edec667a5387bfae85752854
Arg [19] : 0000000000000000000000007c361828849293684ddf7212fd1d2cb5f0aade70
Arg [20] : 0000000000000000000000009d3f4eeb533b8e3c8f50dbbd2e351d1bf2987908
Arg [21] : 000000000000000000000000865dc9a621b50534ba3d17e0ea8447c315e31886
Arg [22] : 000000000000000000000000324e0b53cefa84cf970833939249880f814557c6
Arg [23] : 000000000000000000000000ce156d5d62a8f82326da8d808d0f3f76360036d0
Arg [24] : 00000000000000000000000026bdde6506bd32bd7b5cc5c73cd252807ff18568
Arg [25] : 000000000000000000000000d6efc21d8c941aa06f90075de1588ac7e912fec6
Arg [26] : 000000000000000000000000e0d62cc9233c7e2f1f23fe8c77d6b4d1a265d7cd
Arg [27] : 0000000000000000000000000b54b916e90b8f28ad21da40638e0724132c9c93
Arg [28] : 000000000000000000000000629cd43eaf443e66a9a69ed246728e1001289eac
Arg [29] : 0000000000000000000000000709e442a5469b88bb090dd285b1b3a63fb0c226
Arg [30] : 00000000000000000000000094a2ffdbdbd84984ac7967878c5c397126e7bbbe
Arg [31] : 00000000000000000000000051ec66e63199176f59c80268e0be6ffa91fab220
Arg [32] : 0000000000000000000000000a71e650f70b35fca8b70e71e4441df8d44e01e9
Arg [33] : 000000000000000000000000c1b6052e707dff9017deab13ae9b89008fc1fc5d
Arg [34] : 0000000000000000000000009be95ef84676393588e49ad8b99c9d4cdfdaa631
Arg [35] : 000000000000000000000000fffff6e70842330948ca47254f2be673b1cb0db7
Arg [36] : 0000000000000000000000000000ce08fa224696a819877070bf378e8b131acf
Arg [37] : 000000000000000000000000c2cb4b1bcaebaa78c8004e394cf90ba07a61c8f7
Arg [38] : 000000000000000000000000b2812370f17465ae096ced55679428786734a678
Arg [39] : 0000000000000000000000003eb851c3959f0d37e15c2d9476c4adb46d5231d1
Arg [40] : 000000000000000000000000ad286cf287b91719ee85d3ba5cf3da483d631dba
Arg [41] : 000000000000000000000000bd37a957773d883186b989f6b21c209459022252
Arg [42] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [43] : 000000000000000000000000000000000000000000000000120e149b64c88000
Arg [44] : 0000000000000000000000000000000000000000000000bdbc41e0348b300000
Arg [45] : 0000000000000000000000000000000000000000000001faebc1969c256d50a0
Arg [46] : 00000000000000000000000000000000000000000000097950c4685a7a837de0
Arg [47] : 000000000000000000000000000000000000000000000fcc48cebda35139d542
Arg [48] : 000000000000000000000000000000000000000000000086a657deffaa010000
Arg [49] : 000000000000000000000000000000000000000000000065d7d85462acd3da8f
Arg [50] : 0000000000000000000000000000000000000000000001e770370c4f2ea5d15f
Arg [51] : 00000000000000000000000000000000000000000000003c3aee0b89d2b5def3
Arg [52] : 0000000000000000000000000000000000000000000000f1ba9428d88d218f07
Arg [53] : 0000000000000000000000000000000000000000000004999b2f3e9d028c0000
Arg [54] : 00000000000000000000000000000000000000000000082a1e88793a59061680
Arg [55] : 000000000000000000000000000000000000000000000140e1e7ae7eba1b740b
Arg [56] : 00000000000000000000000000000000000000000000005510e6a88fc67a95ac
Arg [57] : 00000000000000000000000000000000000000000000022905914c52531970b8
Arg [58] : 00000000000000000000000000000000000000000000003043f2e885c284efa2
Arg [59] : 0000000000000000000000000000000000000000000001103208f6d5d3359745
Arg [60] : 00000000000000000000000000000000000000000000002940ff1c0c98440000
Arg [61] : 000000000000000000000000000000000000000000000a69a2abeb1e9e5bd87d
Arg [62] : 00000000000000000000000000000000000000000000054e3f87fb8377f44764
Arg [63] : 00000000000000000000000000000000000000000000005579e670fe92a4623b
Arg [64] : 0000000000000000000000000000000000000000000000c6a036eb4bc7400000
Arg [65] : 0000000000000000000000000000000000000000000000671e2f005f4a0cd2cf
Arg [66] : 0000000000000000000000000000000000000000000007672c4b23049f1b1b80
Arg [67] : 0000000000000000000000000000000000000000000001fc7dbd2c5e27fddd7a
Arg [68] : 000000000000000000000000000000000000000000000153bc08d918b19bf49e
Arg [69] : 0000000000000000000000000000000000000000000000056bc75e2d63100000
Arg [70] : 0000000000000000000000000000000000000000000000c862e9c7a8dc4a0f82
Arg [71] : 00000000000000000000000000000000000000000000002824396cc4d1400000
Arg [72] : 00000000000000000000000000000000000000000000007ad7113237ab280000
Arg [73] : 000000000000000000000000000000000000000000000050438f718496692613
Arg [74] : 00000000000000000000000000000000000000000000053b1b7e838a88939a67
Arg [75] : 000000000000000000000000000000000000000000000020cc0fc69297540000
Arg [76] : 00000000000000000000000000000000000000000000005bdf9cb345eaf862e2
Arg [77] : 000000000000000000000000000000000000000000000325664b203d8a840000
Arg [78] : 00000000000000000000000000000000000000000000000168d28e3f00280000
Arg [79] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [80] : 00000000000000000000000000000000000000000000000000000000000000b0
Arg [81] : 000000000000000000000000000000000000000000000000000000000000001e
Arg [82] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [83] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [84] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [85] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [86] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [87] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [88] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [89] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [90] : 0000000000000000000000000000000000000000000000000000000000000043
Arg [91] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [92] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [93] : 000000000000000000000000000000000000000000000000000000000000006d
Arg [94] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [95] : 000000000000000000000000000000000000000000000000000000000000001d
Arg [96] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [97] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [98] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [99] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [100] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [101] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [102] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [103] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [104] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [105] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [106] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [107] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [108] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [109] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [110] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [111] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [112] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [113] : 00000000000000000000000000000000000000000000000000000000000000d0
Arg [114] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [115] : 00000000000000000000000000000000000000000000000000000000000000d0
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.